[英]How to map multiple entities from LINQ query into a new entity using a common map method
以下代碼與我的解決方案非常相似,不同之處僅在於“ entitiesA”和“ entitiesB”集合的值使用LINQ數據上下文存儲在SQL Server數據庫中。 該代碼在控制台應用程序中運行完美,但是當從數據庫中檢索值時,系統會顯示“無法將表達式'...'轉換為SQL,也無法將其視為本地表達式。”。 我做錯了什么?
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqSelectDemo
{
class EntityA
{
public int ID { get; set; }
public string StringValue { get; set; }
}
class EntityB
{
public int ID { get; set; }
public int? EntityAID { get; set; }
public int IntValue { get; set; }
}
class EntityC
{
public int ID { get; set; }
public string StringValue { get; set; }
public int IntValue { get; set; }
}
class Program
{
static List<EntityA> entitiesA;
static List<EntityB> entitiesB;
static EntityC MapEntityC(EntityB entityB, EntityA entityA = null)
{
if (entityA == null)
{
entityA = entitiesA.FirstOrDefault(entity => (entity.ID == entityB.EntityAID));
}
return new EntityC()
{
ID = ((entityA != null) ? entityA.ID : 0) + ((entityB != null) ? entityB.ID : 0),
StringValue = (entityA != null) ? entityA.StringValue : null,
IntValue = (entityB != null) ? entityB.IntValue : int.MinValue
};
}
static void Main(string[] args)
{
entitiesA = new List<EntityA>()
{
new EntityA() { ID = 11, StringValue = "string1" },
new EntityA() { ID = 12, StringValue = "string2" },
new EntityA() { ID = 13, StringValue = "string3" },
};
entitiesB = new List<EntityB>()
{
new EntityB() { ID = 21, IntValue = 1, EntityAID = 11 },
new EntityB() { ID = 22, IntValue = 2 },
new EntityB() { ID = 23, IntValue = 3, EntityAID = 13 },
};
List<EntityC> entitiesC1 = entitiesB.GroupJoin(entitiesA, entityB => entityB.EntityAID, entityA => entityA.ID, (entityB, entityA) => new { entityB, entityA = entityA.SingleOrDefault() })
.Select(entity => MapEntityC(entity.entityB, entity.entityA))
.ToList();
List<EntityC> entitiesC2 =
(
from entityB in entitiesB
join entityA in entitiesA on entityB.EntityAID equals entityA.ID into tempEntitiesA
from entityA in tempEntitiesA.DefaultIfEmpty()
select MapEntityC(entityB, entityA)
).ToList();
foreach (EntityC entityC in entitiesC1)
{
Console.WriteLine("ID: {0}, StringValue: '{1}', IntValue: {2}", entityC.ID, entityC.StringValue, entityC.IntValue);
};
Console.WriteLine();
foreach (EntityC entityC in entitiesC2)
{
Console.WriteLine("ID: {0}, StringValue: '{1}', IntValue: {2}", entityC.ID, entityC.StringValue, entityC.IntValue);
};
}
}
}
我認為您不應該創建linq-to-objects
和linq-to-entities
兼容查詢。 即使它們看起來相似,但在功能上卻完全不同。 因此,我提出的解決方案將忽略事物的“ linq-to-objects
方面。
第一步是創建一個包含兩個實體的類。 在這種情況下, EntityA
和EntityB
public class EntityBandA
{
public EntityB EntityB { get;set; }
public EntityA EntityA { get;set; }
}
現在我們需要創建一個IQueryable
轉換方法。 此方法的目的是將新的IQueryable<EntityBandA>
轉換為IQueryable<EntityC>
。 注意-僅在我們對數據庫進行迭代(即ToList
, FirstOrDefault
等)之后,此操作FirstOrDefault
數據庫運行。
static IQueryable<EntityC> MapEntityC(IQueryable<EntityBandA> query)
{
var query = from e in query
select new EntityC()
{
ID = e.EntityA.ID + e.EntityB,
StringValue = e.EntityA.StringValue,
IntValue = e.EntityB != null ? entityB.IntValue : int.MinValue
};
return query;
}
注意,我們刪除了一些空檢查。 當使用linq-to-entities
,它們不是必需的,因為我們的表達式已被翻譯成sql。 如果找不到任何值,它將選擇默認值。 ( Int:0, String:null
)
現在我們需要調整您當前的應用程序以使用我們的新方法
IQueryable<EntityBandA> queryBandA = entitiesB.GroupJoin(entitiesA, entityB => entityB.EntityAID, entityA => entityA.ID,
(entityB, entityA) => new EntityBandA
{
EntityB = entityB,
EntityA = entityA.SingleOrDefault()
});
List<EntityC> entitiesC1 = MapEntityC(queryBandA).ToList();
這意味着Linq To SQL無法MapEntity()
調用映射到相等的SQL表達式。
您需要從Linq To SQL中獲取數據(也許可以通過查詢包含JOIN
的VIEW
來完成,這很容易做到),並且在接收到數據並將其存儲在內存后(在List
),然后將其映射到EntityC
數據類型。
另外,您可以通過將整個表讀入內存中來下載列表entitiesA和entityB,如下所示:
entitiesA = DbContext.EntitiesA.ToList();
entitiesB = DbContext.EntitiesB.ToList();
然后,您可以繼續使用所使用的表達式,因為現在使用的是內存中列表,因此使用的是常規LINQ to Object,而不是LINQ to SQL。
謝謝大家花一點時間寫一個可能的解決方案和/或評論。 所有的想法都很棒。 實際上,原始代碼按預期方式工作。 問題是我不是用平凡的參數而是使用三次運算符來調用映射函數。 就像是:
Select(entity => MapEntityC(entity.entityB,
(entity.entityA != null) ? entity.entityA : new EntityA()));
LINQ to SQL無法轉換為SQL語句。 一旦刪除該表達式並使用了一個簡單的表達式,該代碼就會起作用。 再次感謝您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.