【问题标题】:EntityEntry.Property() throws InvalidOperationException when property does exist当属性确实存在时,EntityEntry.Property() 抛出 InvalidOperationException
【发布时间】:2016-11-11 08:19:44
【问题描述】:

大家好,我有以下课程:

public class EntityA
{
    public Guid Id { get; set; }
    public string Desc { get; set; }

    public EntityB EntityB { get; set; }
}

public class EntityB
{
    public Guid Id { get; set; }
    public Guid EntityAId { get; set; }
    public EntityA EntityA { get; set; }
}

我有以下运行时代码:

var a1 = new EntityA {Desc = "a1"};
var a2 = new EntityA {Desc = "a2"};
dbx.EntityAs.Add(a1);
dbx.EntityAs.Add(a2);

var b1 = new EntityB { EntityAId = a1.Id };
dbx.EntityBs.Add(b1);
dbx.SaveChanges();
b1.EntityAId = a2.Id;
dbx.SaveChanges();

我在我的 DbContext.SaveChanges() 方法中修改了如下代码,试图找出实体中的哪个属性发生了变化以及它的前后值:

foreach (var entity in changedEntites)
{
var entityType = entity.Entity.GetType();

if (entity.State == EntityState.Modified)
{                  
    var properties = entityType.GetProperties();
    var props = new List<object>();
    foreach (var prop in properties)
    {
        if(entityType.GetProperty(prop.Name) == null)
            continue;
        var pp = entityType.GetProperty(prop.Name);
        if(pp.GetValue(entity.Entity) == null)
            continue;

        var p = entity.Property(prop.Name);
        if (p.IsModified)
            props.Add(new { f = prop.Name, o = p.OriginalValue, c = p.CurrentValue });
    }
}
}

有问题的代码在这一行:

var p = entity.Property(prop.Name);

它抛出InvalidOperationException

The property 'EntityA' on entity type 'EntityB' could not be found.
Ensure that the property exists and has been included in the model.

我的问题是为什么即使entityType.GetProperty(prop.Name)entityType.GetProperty(prop.Name).GetValue(entity.Entity) 不为空,entity.Property() 仍然无法找到该属性?

我可以用 try-catch 块包围var p = entity.Property(prop.Name); 并忽略异常,但是让异常在审计场景中不断抛出并不是一件好事。它也会对性能产生影响。

非常感谢任何解决方法。谢谢

【问题讨论】:

    标签: c# entity-framework asp.net-core entity-framework-core .net-core


    【解决方案1】:

    问题在于 Property 方法仅支持原始属性,而您使用导航属性调用它。

    您可以使用通过返回IEntityTypeEntityEntry.Metadata 属性访问的ER Core 元数据服务。在你的情况下,FindProperty 方法,虽然你应该首先使用 GetProperties 而不是反射:

    if (entity.Metadata.FindProperty(prop.Name) == null)
        continue;
    
    var p = entity.Property(prop.Name);
    if (p.IsModified)
        props.Add(new { f = prop.Name, o = p.OriginalValue, c = p.CurrentValue });
    

    【讨论】:

    • 谢谢。这就是我需要的。通过 Google 和 EF 文档站点进行搜索,令人沮丧的是,文档没有提到 Property 方法仅支持原始属性。
    【解决方案2】:

    这是因为 entityEntityEntry。您应该正确命名变量以免混淆:

    foreach (var entiry in changedEntries)
    {
        var entity = entiry.Entity;
        var entityType = entity.GetType();
    
        if (entity.State == EntityState.Modified)
        {                  
            var properties = entityType.GetProperties();
            var props = new List<object>();
            foreach (var prop in properties)
            {
                if(entityType.GetProperty(prop.Name) == null)
                    continue;
                var pp = entityType.GetProperty(prop.Name);
                if(pp.GetValue(entity) == null)
                    continue;
    
                var p = entity.Property(prop.Name);
                if (p.IsModified)
                    props.Add(new { f = prop.Name, o = p.OriginalValue, c = p.CurrentValue });
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多