2017-11-21 10 views
1

パラメータ - (文字列サプライヤー)2つのLinqクエリを1つに結合するにはどうすればよいですか?

var supplierID = db.SupplierTable 
      .Where(m => m.SupplierName.Trim().ToLower() == Supplier.Trim().ToLower()) 
      .Select(m => m.SupplierID).First(); 

var supplierREFs = db.ProductSuppliers 
      .Where(m => m.SupplierID == supplierID) 
      .Select(m => m.SupplierRef); 

上記2つのクエリは1つのクエリに組み合わせることができますか?

+0

これらの2つのテーブルを結合します。 –

+0

最初のクエリを取得して、「supplierID」を持つ2番目のクエリに入れます – CodingYoshi

答えて

2

確かに、あなたは、サブクエリを必要とする:

Supplier = Supplier.Trim(); // do this once and not in the query 

var supplierREFs = db.ProductSuppliers 
    .Where(m => db.SupplierTable 
     .Where(s => m.SupplierID == s.SupplierID) 
     .Any(s => String.Equals(s.SupplierName.Trim(), Supplier, StringComparison.CurrentCultureIgnoreCase)) 
    ) 
    .Select(m => m.SupplierRef); 

このクエリはSupplierName一致がSupplier(ケースを無視して)指定されたすべてのProductSupplierをとります。その後、それはSupplierRefを返します。

サイドノート:SupplierNamesをデータベースに先行/後ろのスペースを入れて保存しない場合は、s.SupplierName.Trim()ではなく、s.SupplierNameと比較してください。

+0

元のTrim()機能がありませんでした。より重要なのは、どの文字列比較がSQLに変換可能であるかです。あなたはこれを(EFで)テストしましたか? –

+0

@HenkHolterman:私は、OPが 'SupplierNames'をデータベースの先頭または末尾のスペースで保存しないことを願っています。しかし、私はトリムを含めるために私のコードを編集しました。はい、「String.Equals」は私が読んだものまでサポートされるべきです。もちろん、私はテストするデータベースがないので、私はそれをテストしていません。 –

+0

@HenkHolterman:Side-note:データベース照合によれば、デフォルトであるため、大文字と小文字を区別しません。つまり、もしそれを変更したいのであれば、 'StringComparison.CurrentCultureIgnoreCase'の代わりに' StringComparison.CurrentCulture'を使うだけでは十分ではないかもしれません。そして、彼は本当にCOLLATE列を変更するか、Linq-To-Objects(大文字小文字を区別しない 'Where'-filter)を使う必要があります。 –

0

2つのエンティティを結合することができます。

Supplier = Supplier.Trim().ToLower(); 

var supplierREFs = (from st in db.SupplierTable 
           join sr in supplierREFs on st.SupplierID equals sr.SupplierID 
           where 
           st.SupplierName.Trim().ToLower() == Supplier 
           select sr) 
0

はどうやらProductSuppliersTableからごSupplierTableとProductSupplier項目からサプライヤー項目間の1対多の関係があります:

すべてのサプライヤーがゼロ以上ProductSuppliersを持ち、すべてのProductSupplierは正確に一つのサプライヤーに属します。

あなたのone-to-many relationship according to the default entity framework conventions次のようなクラスがあります設定した場合:

class Supplier 
{ 
    public int Id {get; set;} 
    // Every Supplier has zero or more ProductSupplierTables: 
    public virtual ICollection<ProductSuppierTable> ProductSupplierTables {get; set;} 

    public string SupplierName {get; set;} 
    ... 
} 

class ProductSupplier 
{ 
    public int Id {get; set;} 
    // every ProductSupplier belongs to exactly one Supplier using foreign key 
    public virtual Supplier Supplier {get; set;} 
    public int SupplierId {get; set;} 

    public string SupplierRef {get; set;} 
    ... 
} 

をそれはいくつかの識別子名が異なることかもしれないが、アイデアが明確である:あなたのサプライヤーは、仮想ICollectionをする必要がProductSuppliers、およびProductSupplierには、サプライヤおよび仮想サプライヤに対する外部キーが必要です。

これを正しく実行すると、エンティティフレームワークはプライマリキーと外部キーを認識し、正しいテーブルを作成します。

あなたのDbContextとあなたのDbSetsがこの1対多の関係について知っていることは素晴らしいことです。 ProductSuppliersを持つサプライヤが必要なときはいつでも、外部キーのジョインを実行する必要はありません。代わりにICollectionを使用できます。

あなたが望むものを自分の言い回しにします。

私はサプライヤーの名前を持っていると私は一緒にサプライヤーの ProductSuppliersからすべてSupplierRefsと、この 名に等しいトリム小文字の名前を持つ 私SupplierTableから最初のサプライヤーのアイテムが欲しいです。

using (var dbContext = new MyDbContext()) 
{ 
    string supplierName = Supplier.Trim().ToLower() 
    dbContext.Suppliers 
     .Where(supplier => String.ToLower(supplier.SupplierName) == supplierName) 
     .Select(supplier => new 
     { // to improve performance: select only the properties you'll use 
      SupplierId = supplier.Id, 
      ... 

      // select also all the SupplierRefs from its ProductSuppliers: 
      SupplierRefs = supplier.ProductSupplier 
       .Select(productSupplier => productSupplier.SupplierRef) 
       .ToList(), 
     }) 
     // I only want the First (or default) of these suppliers: 
     .FirstOrDefault(); 
    } 
} 

エンティティフレームワークは、あなたの1対多の知っている、とその外部キーは、このために使用されます。 Entity Frameworkは適切な結合を行い、あなたのために選択します。

関連する問題