2015-05-28 16 views
7

具有下面的例子:LINQ到實體 - SQL查詢 - 如果列表中包含的對象有2個屬性(或更多)

var myIds = db.Table1.Where(x=>x.Prop2 == myFilter).Select(x=>x.Id).ToList(); 
var results = db.Table2.Where(x=> myIds.Contains(x.T1)).ToList(); 

這部分是直線前進。

但是,我現在面對的在我的「篩選器列表」有2個屬性,而不是隻有一個「輕微」的變化:

// NOTE: for stackoverflow simplification I use a basic query to 
// get my "myCombinationObject". 
// In reality this is a much more complex case, 
// but the end result is a LIST of objects with two properties. 
var myCombinationObject = db.Table3.Where(x=>x.Prop3 == myFilter) 
            .Select(x=> new { 
              Id1 = x.T1, 
              Id2 = x.T2 
            }).ToList(); 

var myCombinationObjectId1s = myCombinationObject.Select(x=>xId1).ToList(); 
var myCombinationObjectId2s = myCombinationObject.Select(x=>xId2).ToList(); 

// step#1 - DB SQL part 
var resultsRaw = db.Tables.Where(x=> 
        myCombinationObjectId1s.Contains(x.Prop1) 
        || myCombinationObjectId2s.Contains(x.Prop2)) 
       .ToList(); 
// step#2 - Now in memory side - where I make the final combination filter. 
var resultsFiltered = resultsRaw.Where(x=> 
      myCombinationObject.Contains( 
         new {Id1 = x.Prop1, Id2 = x.Prop2 } 
      ).ToList(); 

我的問題:是它甚至有可能合併的步驟# 2在步驟#1(在LINQ查詢實體)?

+0

不幸的是,它是複雜的問題。請閱讀我的問題 - 或許真的將是有益的:http://stackoverflow.com/questions/25563338/linq-simulating-multiple-columns-in-in-clausule –

回答

2

我我曾經管理過一次做你想做的事情,但是它非常困難並且需要改變一下實體模型。你需要一個實體來映射類型

new {Id1 = x.Prop1, Id2 = x.Prop2 } 

所以你需要enity有2個屬性 - Id1和Id2。如果你有一個 - 偉大的,如果不是那麼這樣的實體添加到模型:

public class CombinationObjectTable 
{ 
    public virtual Guid Id1 { get; set; } 
    public virtual Guid Id2 { get; set; } 
} 

將它添加到你的模型:

public DbSet<CombinationObjectTable> CombinationObjectTable { get; set; } 

創建新的遷移,並將其應用於數據庫(數據庫將有現在的附加表CombinationObjectTable)。之後,你開始建立一個查詢:

DbSet<CombinationObjectTable> combinationObjectTable = context.Set<CombinationObjectTable>(); 
StringBuilder wholeQuery = new StringBuilder("DELETE * FROM CombinationObjectTable"); 
foreach(var obj in myCombinationObject) 
{ 
    wholeQuery.Append(string.Format("INSERT INTO CombinationObjectTable(Id1, Id2) VALUES('{0}', '{1}')", obj.Id1, obj.Id2); 
} 
wholeQuery.Append(
    db.Tables 
     .Where(x=> 
       myCombinationObjectId1s.Contains(x.Prop1) 
       || myCombinationObjectId2s.Contains(x.Prop2)) 
     .Where(x=> 
      combinationObjectTable.Any(ct => ct.Id1 == x.Id1 && ct.Id2 == x.Id2) 
     ).ToString(); 
    ); 

var filteredResults = context.Tables.ExecuteQuery(wholeQuery.ToString()); 

感謝這你的主要查詢保持寫在LINQ。如果你不想添加新的表到你的數據庫,這也是可以實現的。將新類CombinationObjectTable添加到模型中,生成新的遷移以添加它,然後從遷移代碼中刪除創建該表的代碼。之後,申請遷移。這樣數據庫模式不會被改變,但EF會認爲數據庫中存在CombinationObjectTable。相反,它您需要創建一個臨時表來保存數據:

StringBuilder wholeQuery = new StringBuilder("CREATE TABLE #TempCombinationObjectTable(Id1 uniqueidentifies, Id2 uniqueidentifier);"); 

當你在你的LINQ查詢變化CombinationObjectTable調用ToString方法來#TempCombinationObjectTable:

... 
.ToString() 
.Replace("CombinationObjectTable", "#TempCombinationObjectTable") 

其他事情值得考慮會使用查詢參數在INSERT語句中傳遞值而不是僅僅在查詢中包含它們 - 這當然也可以用EF來實現。這個解決方案並沒有完全準備好應用,而是一些提示您可能會選擇哪個解決方案。

2

你能不能做這樣的事情:

var result= 
     db.Tables 
      .Where(t=> 
       db.Table3 
       .Where(x=>x.Prop3 == myFilter) 
       .Any(a=>a.T1==t.Prop1 || a.T2==t.Prop2) 
     ).ToList(); 
+0

基於我的問題在哪裏我簡化了我的問題(更容易遷移到stackoverflow)與myCombinationObject,是的,我會說是的,這是一個正確的答案。然而實際上我的myCombinationObject不是來自db。相反,表3是其他複雜的LOONNNGGG查詢的結果,其中甚至使用「讓let temp1 = xxxxxx」類型的「let」,爲此我仍然沒有解決方案....任何方法謝謝你的回答,我肯定會在將來用於其他案例) – Dryadwoods

1

如果你只是想避免中間結果(同時也創造了第二中間的列表),你可以做以下

var resultsFiltered = db.Tables.Where(x=> 
       myCombinationObjectId1s.Contains(x.Prop1) 
       || myCombinationObjectId2s.Contains(x.Prop2)) 
      .AsEnumerable() // everything past that is done in memory but isn't materialized immediately, keeping the streamed logic of linq 
      .Where(x=> 
       myCombinationObject 
        .Contains(new {Id1 = x.Prop1, Id2 = x.Prop2 }) 
      .ToList(); 
+0

我感謝你的幫助,但是你沒有給我提供任何問題的答案(只有一個查詢LINQ TO ENTITIES) – Dryadwoods

+0

@Dryadwoods它會更容易告訴你,如果我們的代碼實際上沒有「簡化爲」stackoverflow「版本,如果你想在數據庫端完成所有這一切,我們需要知道你所做的一切,重新做 –

相關問題