Entity Framework will only set related entity property to “null” if I first get the property

前端 未结 6 977
难免孤独
难免孤独 2021-01-14 00:50

Edit This seems to occur for any Entity property that references another entity in one direction. In other words, for the below example, the fact

6条回答
  •  执笔经年
    2021-01-14 01:15

    Personally, I think Nathan's answer (lazy-loading inside the property setter) is the most robust. However, it mushrooms your domain classes (10 lines per property) and makes it less readable.

    As another workaround, I compiled two methods into a extension method:

    public static void SetToNull(this TEntity entity, Expression> navigationProperty, DbContext context = null)
        where TEntity : class
        where TProperty : class
    {
        var pi = GetPropertyInfo(entity, navigationProperty);
    
        if (context != null)
        {
            //If DB Context is supplied, use Entry/Reference method to null out current value
            context.Entry(entity).Reference(navigationProperty).CurrentValue = null;
        }
        else
        {
            //If no DB Context, then lazy load first
            var prevValue = (TProperty)pi.GetValue(entity);
        }
    
        pi.SetValue(entity, null);
    }
    
    static PropertyInfo GetPropertyInfo(    TSource source,    Expression> propertyLambda)
    {
        Type type = typeof(TSource);
    
        MemberExpression member = propertyLambda.Body as MemberExpression;
        if (member == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a method, not a property.",
                propertyLambda.ToString()));
    
        PropertyInfo propInfo = member.Member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.",
                propertyLambda.ToString()));
    
        if (type != propInfo.ReflectedType &&
            !type.IsSubclassOf(propInfo.ReflectedType))
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a property that is not from type {1}.",
                propertyLambda.ToString(),
                type));
    
        return propInfo;
    }
    

    This allows you to supply a DbContext if you have one, in which case it will use the most efficient method and set the CurrentValue of the Entry Reference to null.

    entity.SetToNull(e => e.ReferenceProperty, dbContext);
    

    If no DBContext is supplied, it will lazy load first.

    entity.SetToNull(e => e.ReferenceProperty);
    

提交回复
热议问题