调用SaveChanges()时如何获取外键的导航属性?

时间:2015-05-10 04:46:05

标签: entity-framework logging code-first savechanges

我先使用EF5代码。

我们有一个方法

LogHistoryTracking(DbEntityEntry entity)

在调用SaveChanges时记录更改。

SaveChanges,我们获取已更改的实体并转入LogHistoryTracking

var changedEntities = ChangeTracker.Entries().ToList();


但是当我访问

changedEntity.OriginalValues.PropertyNames

外键对象没有属性(只有外键ID - 但是如果这里只有id,我们怎样才能得到数据?)。

我也试图谷歌寻求解决方案,但这个问题可能不那么受欢迎。

this article,但它不起作用。

感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:0)

如果您希望可以访问您的实体属性,则必须在访问它们之前'Include'。就像在下面的示例中获得第一个cutomer的订单:

    var orders = context.Customers
   .Include("Orders")
   .First().Orders;

在此示例中,如果您不致电.Include("Orders"),则不会有Customer.Orders。如果你有外键并忘记包含外键的导航属性,也是如此。这是因为键(ID)是对象的一部分而导航属性不是。

让我们看一个现实世界的例子:

public class Employee : Entity
{
    public virtual int CompanyUserId { get; set; }
    public virtual CompanyUser CompanyUser { get; set; }
    //... cut out for brevity
}

如果你让这样的员工这样:

var employees = context.Employees;

您将无法访问员工[0] .CompanyUser context.SaveChanges()因为延迟加载。连接在context.SaveChanges()之后处理,因此不再提取数据。

但如果你打电话:

var employees = context.Employees
           .Include("CompanyUser")
           .ToArray();

您可以在context.SaveChanges之前立即访问employees [0] .CompanyUser.SomeProperty,无论延迟加载,因为ToArray()将执行查询并使用" includes"来获取实体。 / p>

如果你打电话:

var employees = context.Employees
               .Include("CompanyUser");

然后,即使在带有延迟加载的context.SaveChanges()之后你也会有雇员[0] .CompanyUser.SomeProperty,因为你告诉EF要包括" CompanyUser"执行查询之前的属性。执行时,EF将包含命名属性。

<强>更新 拦截DbContext可以至少以两种不同的方式完成。 第一个 - 覆盖SaveChanges()或SaveChangesAsync,因为它是虚拟的:

public class MyDbContext : DbContext
{
    public event Action<MyDbContext> SavingChanges = _ => { };

    public override int SaveChanges()
    {
        this.SavingChanges(this);
        return base.SaveChanges();
    }
}
没有直接覆盖的

第二种方式是将DbContext隐藏在这个界面中(这是来自真实项目):

public interface IUnitOfWork : IDisposable
{
    void Commit();
}

第三种方式(稍有不同)是intercepting Db调用。 存在第四种方式,但这取决于您使用的IoC。如果您使用Castle Windsor,则可以使用interceptors。我想,每个IoC都有自己的拦截方式。