Linq'den SQL'e nasıl yapılır "nerede [sütun] (değerler listesi)" içinde


102

Kimliklerin bir listesini aldığım bir işlevim var ve id ile ilişkili bir açıklamayla eşleşen bir listeyi döndürmem gerekiyor. Örneğin:

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

Dolayısıyla, bunun için sql'yi kendim oluşturuyor olsaydım, aşağıdakine benzer bir şey yapardım (burada in cümlesi, codeIds argümanındaki tüm değerleri içerir):

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

Linq to Sql'de "IN" cümlesinin eşdeğerini bulamıyorum. Şimdiye kadar bulduğum en iyisi (işe yaramıyor):

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

Sorun şu ki, linq to sql için dinamik olarak bir "OR" cümleleri listesi oluşturamıyorum, çünkü bunlar derleme zamanında ayarlanmışlar.

Bir sütunu kontrol eden bir where cümlesinin Linq to Sql kullanarak dinamik bir değerler listesinde olduğunu nasıl başarabiliriz?

Yanıtlar:


161

Kullanım

where list.Contains(item.Property)

Veya sizin durumunuzda:

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

Ama bunu noktalı gösterimle de yapabilirsiniz:

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

CodeId Tamsayı ise nasıl kullanılır?
Kiran Solkar

2
@KiranSolkar: O zaman muhtemelen a codeIDsolur List<int>ve her şey yoluna girer .
Jon Skeet

@JonSkeet Bu büyük / küçük harfe duyarlı değil mi? CodeID'ler büyük harfli dizelerden oluşan bir listeyse ve codeData.codeId küçük harfli bir dizeyse başarısız olur.
PersyJack

@PersyJack: Soruda, büyük / küçük harfe duyarlı olmamasıyla ilgili hiçbir şey yoktu. Olup olunmayacağına gelince, LINQ to SQL'in varsayılan olarak büyük / küçük harf duyarlılığını uygulayıp uygulamadığını veya db ayarlarının onu yönetmesine izin verip vermediğini hatırlayamıyorum.
Jon Skeet

1
@PersyJack LINQ to SQL, büyük / küçük harf duyarlılığı için veritabanı ayarlarını kullanarak SQL Server'da çalışan T-SQL sorgusunu oluşturur. Dikkatli olunmazsa ve sorgu sonuçlarını yerine getirirse, LINQ'yu bellek içi nesnelere uygulamadan önce, uyumsuz büyük / küçük harf duyarlılığının sonuçlarına maruz kalabilirler.
Zarepheth

26

Ayrıca şunları da kullanabilirsiniz:

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

1
IQToolkit uygulamamız desteklemediği için bunu kullanmak zorunda kaldım .Contains ()
DJ van Wyk

1

Yöntemi Jon Skeet'in cevabında kullanıyordum ama kullanırken başka bir tane daha geldi Concat. ConcatYöntem sınırlı bir testtir biraz daha iyi bir performans, ama bir güçlük ve ben muhtemelen sadece sopa ile Contains, ya da belki benim için bunu yapmanın bir yardımcı yöntemini yazacağım. Her iki durumda da, ilgilenen varsa işte başka bir seçenek:

Yöntem

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

Performans testi

Bu uzaktan bilimsel değildi. Veritabanınızın yapısının ve listedeki kimliklerin sayısının önemli bir etkisi olacağını tahmin ediyorum.

Her denemede 100 deneme yaptığım Concatve Containsher denemenin rastgele seçilmiş birincil anahtarlar listesi tarafından belirlenen 25 satırı seçmeyi içerdiği bir test kurdum . Bunu yaklaşık bir düzine kez çalıştırdım ve çoğu zaman Concatyöntem% 5-10 daha hızlı çıkıyor, ancak bir kez Containsyöntem sadece bir smidgen tarafından kazanılıyor.


0
 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

0

HashSet kullanarak bunu nasıl yapıyorum

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

HashSet temelde neredeyse O (1) 'e yakın olduğundan karmaşıklığınız O (n) olarak kalır.


Bu, LINQ-to-SQL ile ilgilidir. Bu tür LINQ-to-object değerlendirmeleri geçerli değildir.
Gert Arnold

ICollection bir LINQ-SQL'den de gelebilir, bu genel bir yoldur
MG

Soru, doğru SQL'e çevrilen bir ifadenin nasıl oluşturulacağıyla ilgilidir. Bunun yerel bir koleksiyonun nasıl aranacağıyla ilgisi yok. Cevabınız yalnızca bu ayrımın farkında olmayan gelecekteki okuyucuları yanıltacaktır.
Gert Arnold
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.