首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架代码首先审计多对多和一对多的问题。

实体框架代码首先审计多对多和一对多的问题。
EN

Stack Overflow用户
提问于 2015-08-20 13:58:45
回答 1查看 687关注 0票数 3

我一直试图创建一个审计跟踪,尝试从TrackChanges、重写SaveChanges()、简单地获取实体和使用DbEntityEntry.OriginalValues获取原始值的许多不同方法,所有这些方法最终归结为相同的问题。当我将另一个模型引用为ICollection时,它不会在实体中记录该模型。作为对此问题的一个非常基本的解释,请参阅下面的代码:

代码语言:javascript
复制
public void Update(Project project)
{
    _ctx.OriginalValues(project);
    _ctx.Projects.Attach(project);
    _ctx.Entry(project).State = EntityState.Modified;
    _ctx.SaveChanges(project);
}

上面的.OriginalValues在引发保存更改之前将实体传递给此方法,并且我能够在用户更改之前读取实体中的值。OriginalValues方法如下所示:

代码语言:javascript
复制
public void OriginalValues(object entity)
{
    var entry = this.Entry(entity);               
    System.Reflection.PropertyInfo[] names = entity.GetType().GetProperties();            

    foreach (var property in names)
    {               
        var n = entry.OriginalValues[property.Name];                   
    }
}

上面我理解的方法并不是很优雅,也不是最好的实践,但它是尝试从我的实体读取原始值的一系列尝试中的最新尝试。

当此代码运行时,property.Name将得到一个名为“Teams”的名称,该名称在项目模型中被引用如下:

代码语言:javascript
复制
public class Project
{       
    public int Id { get; set; } // PK
    public string Name { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int MarketId { get; set; } // FK
    [ForeignKey("MarketId")]
    public Market Market { get; set; } // FK Nav   
    public ICollection<Team> Teams { get; set; } // Many to Many Nav 
}

抛出一个错误,它告诉我它还没有映射到Project,即使我已经使用了fluent API和数据注释来尝试并获得一个映射。

这是一个例子,我有相同的情况发生在其他模型,但与许多到许多关系。

我是一个研究生开发人员,因此,没有大量的暴露在.net,我希望有人可以提供任何建议或支持,如果可能的话!

谢谢

编辑:显示错误消息:

“Team”属性不存在或未映射为“Project”类型。 描述:在执行当前web请求时发生了未处理的异常。请查看堆栈跟踪以获得有关错误的更多信息,以及它起源于代码的位置。 例外详细信息: System.ArgumentException:“Team”属性不存在,或者没有映射到“Project”类型。 源错误:

代码语言:javascript
复制
Line 78:             foreach (var property in names)
Line 79:             {               
Line 80:                 var n = entry.OriginalValues[property.Name];                   
Line 81:                 
Line 82:             }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-20 15:45:29

出现此错误是因为EF将每个条目的值保存在自己的对象中,因此导航属性值将保存在它们的条目中,因此它们不在当前对象的OriginalValues中。可以访问导航属性,如下所示:

代码语言:javascript
复制
foreach (var property in names)
{
    var m = entry.Member(property.Name);
    if (m is DbPropertyEntry)//simple property
    {
         var p = entry.Property(property.Name);
    }
    if (m is DbReferenceEntry)//navigation to single object
    {
         var r = entry.Reference(property.Name);
    }
    if (m is DbCollectionEntry)//navigation to collection
    {
         var c = entry.Collection(property.Name);
    }
}

然后,您可以将每个导航对象视为新对象,并检索它们的原始值。

建议: EF内部有一个跟踪系统,可以跟踪对对象图所做的所有更改,您可以查询该跟踪系统并记录更改,如下所示。没有必要跟踪引用,因为如果它们有更改,那么EF就会检测到它。

代码语言:javascript
复制
public void OriginalValues(object entity)
{
    ChangeTracker.DetectChanges();
    var changed = ChangeTracker.Entries()
            .Where(x=>x.State != EntityState.Unchanged).ToList();
    foreach (var entry in changed)
    {
        switch (entry.State)
        {
            case EntityState.Added:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "created:");
                foreach(var name in entry.CurrentValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
                }
            break;
            case EntityState.Deleted:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "deleted:");
                foreach(var name in entry.OriginalValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
                }
            break;
            case EntityState.Modified:
                Debug.WriteLine("object of type " + entry.Entity.GetType().Name 
                   + "updated:");
                Debug.WriteLine("current values:");
                foreach(var name in entry.CurrentValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
                }
                Debug.WriteLine("original values:");
                foreach(var name in entry.OriginalValues.PropertyNames)
                {
                    Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
                }
            break;
         }
     }
 }

注意:删除对象时,确保将状态设置为Deleted

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32120315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档