join tümcesi (C# Başvurusu)
join
yan tümcesi, nesne modelinde doğrudan ilişkisi olmayan farklı kaynak dizilerindeki öğeleri ilişkilendirmek için kullanışlıdır. Tek gereksinim, her kaynaktaki öğelerin eşitlik için karşılaştırılabilir bir değer paylaşmasıdır. Örneğin, bir gıda dağıtımcısının belirli bir ürünün tedarikçilerinin listesi ve alıcıların listesi olabilir. join
Bir yan tümcesi, örneğin, bu ürünün aynı belirtilen bölgede bulunan tedarikçilerinin ve alıcılarının listesini oluşturmak için kullanılabilir.
Yan join
tümcesi, giriş olarak iki kaynak dizisi alır. Her dizideki öğeler, diğer dizideki karşılık gelen bir özellikle karşılaştırılabilir bir özellik olmalıdır veya içermelidir. join
yan tümcesi, özel equals
anahtar sözcüğünü kullanarak belirtilen anahtarları eşitlik için karşılaştırır. yan tümcesi join
tarafından gerçekleştirilen tüm birleşimler eş birleşimlerdir. Yan join
tümcesinin çıkışının şekli, gerçekleştirdiğiniz belirli birleştirme türüne bağlıdır. En yaygın üç birleştirme türü şunlardır:
İç birleştirme
Gruba katılma
Sol dış birleştirme
İç birleştirme
Aşağıdaki örnekte basit bir iç eş birleşim gösterilmektedir. Bu sorgu , "ürün adı / kategori" çiftlerinden oluşan düz bir dizi oluşturur. Aynı kategori dizesi birden çok öğede görünür. öğesinden categories
bir öğenin eşleşen products
bir öğesi yoksa, bu kategori sonuçlarda görünmez.
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence
Daha fazla bilgi için bkz. İç birleşimler gerçekleştirme.
Gruba katılma
İfade join
içeren yan into
tümceye grup birleştirme adı verilir.
var innerGroupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new { CategoryName = category.Name, Products = prodGroup };
Grup birleştirme, sol kaynak dizisindeki öğeleri sağ taraftaki kaynak dizisindeki bir veya daha fazla eşleşen öğeyle ilişkilendiren hiyerarşik bir sonuç dizisi oluşturur. Grup katılımının ilişkisel terimlerde eşdeğeri yoktur; temelde bir nesne dizileri dizisidir.
Sağ kaynak dizisinden sol kaynaktaki bir öğeyle eşleşen öğe bulunamazsa, join
yan tümcesi bu öğe için boş bir dizi oluşturur. Bu nedenle, sonuç dizisinin gruplar halinde düzenlenmesi dışında, grup birleştirme hala temel olarak bir iç birleşimdir.
Yalnızca bir grup katılımının sonuçlarını seçerseniz öğelere erişebilirsiniz, ancak eşleşebilecekleri anahtarı belirleyemezsiniz. Bu nedenle, önceki örnekte gösterildiği gibi grup birleştirmenin sonuçlarını anahtar adına da sahip yeni bir türe seçmek genellikle daha yararlıdır.
Elbette bir grup birleştirme işleminin sonucunu başka bir alt sorgunun oluşturucu olarak da kullanabilirsiniz:
var innerGroupJoinQuery2 =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from prod2 in prodGroup
where prod2.UnitPrice > 2.50M
select prod2;
Daha fazla bilgi için bkz. Gruplandırılmış birleştirmeleri gerçekleştirme.
Sol dış birleştirme
Sol dış birleşimde, doğru sırada eşleşen öğe olmasa bile sol kaynak dizisindeki tüm öğeler döndürülür. LINQ'de sol dış birleşim gerçekleştirmek için yöntemini bir grup birleşimiyle birlikte kullanarak DefaultIfEmpty
sol taraftaki bir öğenin eşleşmesi yoksa üretecek varsayılan sağ taraf öğesini belirtin. Herhangi bir başvuru türü için varsayılan değer olarak kullanabilir null
veya kullanıcı tanımlı bir varsayılan tür belirtebilirsiniz. Aşağıdaki örnekte kullanıcı tanımlı bir varsayılan tür gösterilmektedir:
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product { Name = String.Empty, CategoryID = 0 })
select new { CatName = category.Name, ProdName = item.Name };
Daha fazla bilgi için bkz. Sol dış birleşimleri gerçekleştirme.
equals işleci
Yan join
tümcesi bir eş birleşim gerçekleştirir. Başka bir deyişle, eşleşmeleri yalnızca iki anahtarın eşitliğine göre temel alabilirsiniz. "büyüktür" veya "eşit değil" gibi diğer karşılaştırma türleri desteklenmez. Tüm birleşimlerin eş join
birleşimler olduğunu net bir şekilde ifade etmek için yan tümcesi işleci yerine anahtar sözcüğünü ==
kullanırequals
. Anahtar equals
sözcüğü yalnızca bir join
yan tümcede kullanılabilir ve işleçten ==
bazı önemli yollarla farklıdır. Dizeleri karşılaştırırken, equals
değere göre karşılaştırmak için bir aşırı yükü vardır ve işleç ==
başvuru eşitliğini kullanır. Karşılaştırmanın her iki tarafı da aynı dize değişkenlerine equals
sahip olduğunda ve ==
aynı sonuca ulaştığında: true. Bunun nedeni, bir program iki veya daha fazla eşdeğer dize değişkeni bildirdiğinde, derleyici bunların tümünü aynı konumda depoladığında daha fazla bilgi için bkz . Başvuru eşitliği ve dize stajyerliği . Bir diğer önemli fark null karşılaştırmadır: null equals null
bunu true olarak değerlendiren işleç yerine ==
işleç ile equals
false olarak değerlendirilir. Son olarak kapsam belirleme davranışı farklıdır: ile equals
sol anahtar dış kaynak dizisini, sağ anahtar ise iç kaynağı kullanır. Dış kaynak yalnızca sol tarafındaki equals
kapsamdadır ve iç kaynak dizisi yalnızca sağ taraftaki kapsamdadır.
Eşit olmayanlar
Bir sorguya bağımsız olarak yeni diziler eklemek için birden çok from
yan tümce kullanarak denk olmayanlar, çapraz birleşimler ve diğer özel birleştirme işlemlerini gerçekleştirebilirsiniz. Daha fazla bilgi için bkz. Özel birleştirme işlemleri gerçekleştirme.
Nesne koleksiyonlarındaki birleşimler ve ilişkisel tablolar
LINQ sorgu ifadesinde, birleştirme işlemleri nesne koleksiyonlarında gerçekleştirilir. Nesne koleksiyonları, iki ilişkisel tabloyla tam olarak aynı şekilde "birleştirilemez". LINQ'de, açık join
yan tümceler yalnızca iki kaynak dizisi herhangi bir ilişki tarafından bağlanmadığında gereklidir. LINQ to SQL ile çalışırken, yabancı anahtar tabloları nesne modelinde birincil tablonun özellikleri olarak gösterilir. Örneğin, Northwind veritabanında Customer tablosunun Orders tablosuyla bir yabancı anahtar ilişkisi vardır. Tabloları nesne modeliyle eşlediğinizde, Customer sınıfı, bu Müşteri ile ilişkilendirilmiş Orders koleksiyonunu içeren bir Orders özelliğine sahiptir. Aslında, birleştirme sizin için zaten yapılmıştır.
LINQ to SQL bağlamında ilgili tablolar arasında sorgulama hakkında daha fazla bilgi için bkz. Nasıl yapılır: Veritabanı İlişkilerini Eşleme.
Bileşik anahtarlar
Bileşik anahtar kullanarak birden çok değerin eşitliğini test edebilirsiniz. Daha fazla bilgi için bkz. Bileşik anahtarları kullanarak birleştirme. Bileşik anahtarlar yan group
tümcesinde de kullanılabilir.
Örnek
Aşağıdaki örnek, aynı eşleşen anahtarları kullanarak aynı veri kaynaklarında iç birleşim, grup birleştirme ve sol dış birleştirmenin sonuçlarını karşılaştırır. Konsol ekranındaki sonuçları netleştirmek için bu örneklere bazı ek kodlar eklenir.
class JoinDemonstration
{
#region Data
class Product
{
public string Name { get; set; }
public int CategoryID { get; set; }
}
class Category
{
public string Name { get; set; }
public int ID { get; set; }
}
// Specify the first data source.
List<Category> categories = new List<Category>()
{
new Category {Name="Beverages", ID=001},
new Category {Name="Condiments", ID=002},
new Category {Name="Vegetables", ID=003},
new Category {Name="Grains", ID=004},
new Category {Name="Fruit", ID=005}
};
// Specify the second data source.
List<Product> products = new List<Product>()
{
new Product {Name="Cola", CategoryID=001},
new Product {Name="Tea", CategoryID=001},
new Product {Name="Mustard", CategoryID=002},
new Product {Name="Pickles", CategoryID=002},
new Product {Name="Carrots", CategoryID=003},
new Product {Name="Bok Choy", CategoryID=003},
new Product {Name="Peaches", CategoryID=005},
new Product {Name="Melons", CategoryID=005},
};
#endregion
static void Main(string[] args)
{
JoinDemonstration app = new JoinDemonstration();
app.InnerJoin();
app.GroupJoin();
app.GroupInnerJoin();
app.GroupJoin3();
app.LeftOuterJoin();
app.LeftOuterJoin2();
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
void InnerJoin()
{
// Create the query that selects
// a property from each element.
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { Category = category.ID, Product = prod.Name };
Console.WriteLine("InnerJoin:");
// Execute the query. Access results
// with a simple foreach statement.
foreach (var item in innerJoinQuery)
{
Console.WriteLine("{0,-10}{1}", item.Product, item.Category);
}
Console.WriteLine("InnerJoin: {0} items in 1 group.", innerJoinQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupJoin()
{
// This is a demonstration query to show the output
// of a "raw" group join. A more typical group join
// is shown in the GroupInnerJoin method.
var groupJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select prodGroup;
// Store the count of total items (for demonstration only).
int totalItems = 0;
Console.WriteLine("Simple GroupJoin:");
// A nested foreach statement is required to access group items.
foreach (var prodGrouping in groupJoinQuery)
{
Console.WriteLine("Group:");
foreach (var item in prodGrouping)
{
totalItems++;
Console.WriteLine(" {0,-10}{1}", item.Name, item.CategoryID);
}
}
Console.WriteLine("Unshaped GroupJoin: {0} items in {1} unnamed groups", totalItems, groupJoinQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupInnerJoin()
{
var groupJoinQuery2 =
from category in categories
orderby category.ID
join prod in products on category.ID equals prod.CategoryID into prodGroup
select new
{
Category = category.Name,
Products = from prod2 in prodGroup
orderby prod2.Name
select prod2
};
//Console.WriteLine("GroupInnerJoin:");
int totalItems = 0;
Console.WriteLine("GroupInnerJoin:");
foreach (var productGroup in groupJoinQuery2)
{
Console.WriteLine(productGroup.Category);
foreach (var prodItem in productGroup.Products)
{
totalItems++;
Console.WriteLine(" {0,-10} {1}", prodItem.Name, prodItem.CategoryID);
}
}
Console.WriteLine("GroupInnerJoin: {0} items in {1} named groups", totalItems, groupJoinQuery2.Count());
Console.WriteLine(System.Environment.NewLine);
}
void GroupJoin3()
{
var groupJoinQuery3 =
from category in categories
join product in products on category.ID equals product.CategoryID into prodGroup
from prod in prodGroup
orderby prod.CategoryID
select new { Category = prod.CategoryID, ProductName = prod.Name };
//Console.WriteLine("GroupInnerJoin:");
int totalItems = 0;
Console.WriteLine("GroupJoin3:");
foreach (var item in groupJoinQuery3)
{
totalItems++;
Console.WriteLine(" {0}:{1}", item.ProductName, item.Category);
}
Console.WriteLine("GroupJoin3: {0} items in 1 group", totalItems);
Console.WriteLine(System.Environment.NewLine);
}
void LeftOuterJoin()
{
// Create the query.
var leftOuterQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
select prodGroup.DefaultIfEmpty(new Product() { Name = "Nothing!", CategoryID = category.ID });
// Store the count of total items (for demonstration only).
int totalItems = 0;
Console.WriteLine("Left Outer Join:");
// A nested foreach statement is required to access group items
foreach (var prodGrouping in leftOuterQuery)
{
Console.WriteLine("Group:");
foreach (var item in prodGrouping)
{
totalItems++;
Console.WriteLine(" {0,-10}{1}", item.Name, item.CategoryID);
}
}
Console.WriteLine("LeftOuterJoin: {0} items in {1} groups", totalItems, leftOuterQuery.Count());
Console.WriteLine(System.Environment.NewLine);
}
void LeftOuterJoin2()
{
// Create the query.
var leftOuterQuery2 =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty()
select new { Name = item == null ? "Nothing!" : item.Name, CategoryID = category.ID };
Console.WriteLine("LeftOuterJoin2: {0} items in 1 group", leftOuterQuery2.Count());
// Store the count of total items
int totalItems = 0;
Console.WriteLine("Left Outer Join 2:");
// Groups have been flattened.
foreach (var item in leftOuterQuery2)
{
totalItems++;
Console.WriteLine("{0,-10}{1}", item.Name, item.CategoryID);
}
Console.WriteLine("LeftOuterJoin2: {0} items in 1 group", totalItems);
}
}
/*Output:
InnerJoin:
Cola 1
Tea 1
Mustard 2
Pickles 2
Carrots 3
Bok Choy 3
Peaches 5
Melons 5
InnerJoin: 8 items in 1 group.
Unshaped GroupJoin:
Group:
Cola 1
Tea 1
Group:
Mustard 2
Pickles 2
Group:
Carrots 3
Bok Choy 3
Group:
Group:
Peaches 5
Melons 5
Unshaped GroupJoin: 8 items in 5 unnamed groups
GroupInnerJoin:
Beverages
Cola 1
Tea 1
Condiments
Mustard 2
Pickles 2
Vegetables
Bok Choy 3
Carrots 3
Grains
Fruit
Melons 5
Peaches 5
GroupInnerJoin: 8 items in 5 named groups
GroupJoin3:
Cola:1
Tea:1
Mustard:2
Pickles:2
Carrots:3
Bok Choy:3
Peaches:5
Melons:5
GroupJoin3: 8 items in 1 group
Left Outer Join:
Group:
Cola 1
Tea 1
Group:
Mustard 2
Pickles 2
Group:
Carrots 3
Bok Choy 3
Group:
Nothing! 4
Group:
Peaches 5
Melons 5
LeftOuterJoin: 9 items in 5 groups
LeftOuterJoin2: 9 items in 1 group
Left Outer Join 2:
Cola 1
Tea 1
Mustard 2
Pickles 2
Carrots 3
Bok Choy 3
Nothing! 4
Peaches 5
Melons 5
LeftOuterJoin2: 9 items in 1 group
Press any key to exit.
*/
Açıklamalar
join
tarafından into
takip edilmeyen bir yan tümce bir Join yöntem çağrısına çevrilir. join
tarafından takip into
edilen bir yan tümcesi bir GroupJoin yöntem çağrısına çevrilir.
Ayrıca bkz.
- Sorgu Anahtar Sözcükleri (LINQ)
- Dil ile Tümleşik Sorgu (LINQ)
- Birleştirme İşlemleri
- group tümcesi
- Sol dış birleşimler gerçekleştirme
- İç birleşimler gerçekleştirme
- Gruplanmış birleşimler gerçekleştirme
- Join yan tümcesinin sonuçlarını sıralama
- Bileşik anahtarlar kullanarak birleştirme
- Visual Studio için uyumlu veritabanı sistemleri