T-SQL'de şöyle bir sorguya sahip olabilirsiniz:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Bunu bir LINQ to Entities sorgusunda nasıl çoğaltabilirsiniz? Bu mümkün mü?
Bunu düşünme şekliniz açısından tersine çevirmeniz gerekir. Geçerli öğenin kullanıcı haklarını önceden tanımlanmış uygulanabilir kullanıcı hakları kümesinde bulmak için "in" yapmak yerine, önceden tanımlanmış bir kullanıcı hakları kümesine geçerli öğenin uygulanabilir değerini içerip içermediğini soruyorsunuz. Bu, .NET'te normal bir listede bir öğeyi bulmanın tam olarak aynı yoludur.
LINQ kullanarak bunu yapmanın iki yolu vardır; biri sorgu sözdizimini, diğeri ise yöntem sözdizimini kullanır. Esasen bunlar aynıdır ve tercihinize bağlı olarak birbirlerinin yerine kullanılabilirler:
Sorgu Sözdizimi:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
Metod Sözdizimi:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Bu örnekte kişisel tercihim yöntem sözdizimi olabilir çünkü değişkeni atamak yerine foreach işlemini aşağıdaki gibi anonim bir çağrı üzerinden yapabilirim:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Sözdizimsel olarak bu daha karmaşık görünüyor ve neler olup bittiğini gerçekten anlamak için lambda ifadeleri veya delegeler kavramını anlamanız gerekiyor, ancak görebileceğiniz gibi, bu kodu oldukça yoğunlaştırıyor.
Her şey kodlama tarzınıza ve tercihinize bağlı - verdiğim üç örnek de aynı şeyi biraz farklı şekilde yapıyor.
Alternatif bir yol LINQ bile kullanmaz, aynı yöntem sözdizimini "where" yerine "FindAll" koyarak kullanabilir ve aynı sonucu elde edebilirsiniz, bu da .NET 2.0'da çalışacaktır:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
VS2008/.net 3.5 kullanıyorsanız, Alex James' ipucu #8'e bakın: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
Aksi takdirde sadece array.Contains(someEntity.Member) yöntemini kullanın.
Ben de SQL-IN benzeri bir şeyle çalışmayı denedim - bir Entity Data Model'e karşı sorgulama. Benim yaklaşımım, büyük bir OR ifadesi oluşturmak için bir dize oluşturucu. Bu çok çirkin, ama korkarım ki şu an için tek yol bu.
Şimdi, bu şuna benziyor:
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
Bu bağlamda GUID'lerle çalışmak: Yukarıda görebileceğiniz gibi, sorgu dizesi parçalarında GUID ifself'ten önce her zaman "GUID" kelimesi vardır. Bunu eklemezseniz, ObjectQuery<T>.Where
aşağıdaki istisnayı atar:
Argüman türleri 'Edm.Guid' ve 'Edm.String' bunun için uyumsuzdur işlem., yakın eşittir ifadesi, satır 6, sütun 14.
Bunu MSDN Forumlarında buldum, akılda tutmak faydalı olabilir.
Matthias
... her şeyin daha iyi olacağı bir sonraki .NET ve Entity Framework sürümünü dört gözle bekliyorum :)