【问题标题】:Trying to assign value to nullable Guid property using an expression尝试使用表达式为可为空的 Guid 属性赋值
【发布时间】:2021-07-08 23:12:18
【问题描述】:

大家好,我正在使用表达式树通过使用以下代码创建表达式来将值从源映射到目标

public static class PropertyMapper<TSource, TDest>
{
    private static Expression<Func<TSource, Dictionary<string, MasterSection>, TDest>> _mappingExpression;
    private static Func<TSource, Dictionary<string, MasterSection>, TDest> _mapper;
    static PropertyMapper()
    {
        _mappingExpression = ProjectionMap();
        _mapper = _mappingExpression.Compile();
    }

    public static Func<TSource, Dictionary<string, MasterSection>, TDest> Mapper => _mapper;

    public static Expression<Func<TSource, Dictionary<string, MasterSection>, 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, Dictionary<string, MasterSection>, 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, Expression.Property(Expression.Property(itemParam, "SourceOfData"),typeof(Guid?), "Id"));

尝试 2:

var sourceOfDataPropertyBind = Expression.Bind(sourceOfDataProp, Expression.Property(Expression.Property(itemParam, typeof(Guid?), "SourceOfData"), "Id"));

并试图摆脱上面的这些表达式

  airflowLab => new LibraryLabAirflow
  {              
        IsApproved = true,                 
        SourceOfData = airflowLab.SourceOfData,
        SourceOfDataId = airflowLab.SourceOfData.Id,
   }

谁能告诉我上面的代码哪里做错了,提前谢谢。

【问题讨论】:

  • 谁能告诉我为什么我不能设置属性值

标签: c# .net-core entity-framework-core linq-to-entities expression-trees


【解决方案1】:

不太清楚为什么需要将airflowLab.SourceOfData.Id 分配给显式FK 属性SourceOfDataId,因为在服务器端LINQ to Entities 的上下文中,它应该与直接分配airflowLab.SourceOfDataId 相同。

但是假设出于某种原因您需要它。由于airflowLab.SourceOfData.Id 表达式的静态类型是不可为空 Guid(C# 没有隐式空传播的概念),C# 编译器发出的实际表达式为

SourceOfDataId = airflowLab.SourceOfData.Id

SourceOfDataId = (Guid?)airflowLab.SourceOfData.Id

注意转换为可空的Guid。在映射到Expression.ConvertExpression 术语中,您需要的是类似

Expression.Convert(
    Expression.Property(Expression.Property(itemParam, "SourceOfData"), "Id"),
    typeof(Guid?))

【讨论】:

    猜你喜欢
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 2011-10-12
    • 2011-10-26
    • 1970-01-01
    相关资源
    最近更新 更多