问题描述
大家好,我正在使用表达式树通过使用以下代码创建表达式来将值从源映射到目标
public static class PropertyMapper<TSource,TDest>
{
private static Expression<Func<TSource,Dictionary<string,MasterSection>,TDest>> _mappingExpression;
private static Func<TSource,TDest> _mapper;
static PropertyMapper()
{
_mappingExpression = ProjectionMap();
_mapper = _mappingExpression.Compile();
}
public static Func<TSource,TDest> Mapper => _mapper;
public static Expression<Func<TSource,TDest>> ProjectionMap()
{
var sourceProperties = typeof(TSource).GetProperties().Where(p => p.CanRead);
var destProperties = typeof(TDest).GetProperties().Where(p => p.CanWrite);
var propertyMap =
from d in destProperties
join s in sourceProperties on new { d.Name,d.PropertyType } equals new { s.Name,s.PropertyType }
where d.Name != "SourceOfDataId"
select new { Source = s,Dest = d };
var itemParam = Expression.Parameter(typeof(TSource),"item");
var dictParam = Expression.Parameter(typeof(Dictionary<string,MasterSection>),"dict");
var memberBindings = propertyMap.Select(p => (MemberBinding)Expression.Bind(p.Dest,Expression.Property(itemParam,p.source))).ToList();
var sourceOfDataProp = destProperties.FirstOrDefault(s => s.Name == "SourceOfDataId");
if (sourceOfDataProp != null)
{
// here i am setting one of the inner object(SourceOfData) ID to outer object nullable guid property (SourceOfDataId)
memberBindings.Add(Expression.Bind(sourceOfDataProp,Expression.Property(Expression.Property(itemParam,"SourceOfData"),"Id")));
}
var newExpression = Expression.New(typeof(TDest));
var memberInitExpression = Expression.MemberInit(newExpression,memberBindings);
var projection = Expression.Lambda<Func<TSource,TDest>>(memberInitExpression,itemParam,dictParam);
return projection;
}
}
AirflowsLab = sourceMechanicalData
.AirflowsLab
.Select(a => PropertyMapper<LibraryLabAirflow,LibraryLabAirflow>
.Mapper(a,masterSectionMappedLibrary)).ToList()
我在源实体和目标实体上有这些属性 SourceOfDataId、IsApproved,我试图将 IsApproved 设置为 true 并将 sourceOfDataId 设置为相应的值。
此项目映射错误的值已设置为 SourceOfDataId 而不是内部对象属性 Id 后
实体 LibraryLabAirflow 看起来像这样
public class LibraryLabAirflow
{
[ForeignKey("SourceOfData")]
public Guid? SourceOfDataId { get; set; }
public virtual CodeStandardGuideline SourceOfData { get; set; }
public bool? IsApproved { get; set; }
}
我也尝试过下面的表达式绑定,但都没有工作
尝试 1:
var sourceOfDataPropertyBind = Expression.Bind(sourceOfDataProp,typeof(Guid?),"Id"));
尝试 2:
var sourceOfDataPropertyBind = Expression.Bind(sourceOfDataProp,"Id"));
并试图摆脱上面的这些表达
airflowLab => new LibraryLabAirflow
{
IsApproved = true,SourceOfData = airflowLab.sourceOfData,SourceOfDataId = airflowLab.sourceOfData.Id,}
任何人都可以让我知道我在上面的代码中做错了什么,提前致谢。
解决方法
不太清楚为什么需要将 airflowLab.SourceOfData.Id
分配给显式 FK 属性 SourceOfDataId
,因为在服务器端 LINQ to Entities 的上下文中,它应该与直接分配 airflowLab.SourceOfDataId
相同.
但是出于某种原因,您需要它。由于 airflowLab.SourceOfData.Id
表达式的静态类型是 non nullable Guid
(C# 没有隐式空值传播的概念),C# 编译器为
SourceOfDataId = airflowLab.SourceOfData.Id
会
SourceOfDataId = (Guid?)airflowLab.SourceOfData.Id
注意转换为可为空的 Guid
。在映射到 Expression.Convert
的 Expression
术语中,您需要的是类似
Expression.Convert(
Expression.Property(Expression.Property(itemParam,"SourceOfData"),"Id"),typeof(Guid?))