我先使用EF5代码。
我们有一个方法
LogHistoryTracking(DbEntityEntry entity)
在调用SaveChanges
时记录更改。
在SaveChanges
,我们获取已更改的实体并转入LogHistoryTracking
var changedEntities = ChangeTracker.Entries().ToList();
但是当我访问
changedEntity.OriginalValues.PropertyNames
外键对象没有属性(只有外键ID - 但是如果这里只有id,我们怎样才能得到数据?)。
我也试图谷歌寻求解决方案,但这个问题可能不那么受欢迎。
有this article,但它不起作用。
感谢任何帮助。感谢。
答案 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都有自己的拦截方式。