c# – Linq to entities – SQL Query – 其中list包含具有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(); 我的问题:是否有可能在步骤#1中合并步骤#2(在linq中查询实体)? 解决方法
我曾经设法做过你想做的事情,但这很难,需要改变一下实体模型.您需要一个实体来映射类型
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添加到模型中,生成新的迁移以添加它,然后从迁移代码中删除创建该表的代码.之后应用迁移.这样,db模式不会被更改,但EF会认为数据库中有CombinationObjectTable.而不是它,你需要创建一个临时表来保存数据: StringBuilder wholeQuery = new StringBuilder("CREATE TABLE #TempCombinationObjectTable(Id1 uniqueidentifies,Id2 uniqueidentifier);"); 当您在linq查询上调用ToString方法时,将CombinationObjectTable更改为#TempCombinationObjectTable: ... .ToString() .Replace("CombinationObjectTable","#TempCombinationObjectTable") 值得考虑的其他事情是使用查询参数在INSERT语句中传递值而不是仅仅将它们包含在查询中 – 这当然也可以通过EF实现.此解决方案尚未完全准备好应用,而是提示您可以采用哪种方向解决方案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |