为什么EF5 ChangeTracker代码检查不从IAuditableTable继承的类?

时间:2013-08-11 08:36:56

标签: c# entity-framework

我一直在使用以下代码,我在很多地方建议使用这些代码与Entity Framework 5一起使用。

    foreach (var entry in this.ChangeTracker.Entries()
                 .Where(
                      e => e.Entity is IAuditableTable &&
                     (e.State == EntityState.Added) ||
                     (e.State == EntityState.Modified)))
    {
        IAuditableTable e = (IAuditableTable)entry.Entity;
        if (entry.State == EntityState.Added)
        {
            if (e.CreatedBy == 0) 
                e.CreatedBy = 1;
            if (e.CreatedDate == DateTime.MinValue) 
                e.CreatedDate = DateTime.Now;
        }
        if (e.ModifiedBy == 0) 
            e.ModifiedBy = 1;
        if (e.ModifiedDate == DateTime.MinValue) 
            e.ModifiedDate = DateTime.Now;
    }

这适用于EF5。我只想补充一点:

public partial class Objective : AuditableTable
{

并拥有以下内容:

public abstract class AuditableTable : IAuditableTable
{
    public virtual byte[] Version { get; set; }
    public int CreatedBy { get; set; }
    public DateTime CreatedDate { get; set; }
    public int ModifiedBy { get; set; }
    public DateTime ModifiedDate { get; set; }
}

然而。当我有这样的课程时:

public partial class Objective : AuditableTable
{
    public Objective()
    {
        this.ObjectiveDetails = new List<ObjectiveDetail>();
    }
    public int ObjectiveId { get; set; }
    public int Number { get; set; }
    public string Text { get; set; }
    public virtual ICollection<ObjectiveDetail> ObjectiveDetails { get; set; }
}

然后代码不起作用我在行上发生错误:IAuditableTable e = (IAuditableTable)entry.Entity;它试图将ObjectiveDetail类强制转换为IAuditableTable:

"Unable to cast object of type 'Models.Core.ObjectiveDetail' to type 'Models.Core.IAuditableTable'."

我无法使检查代码生效,除非我从IAuditableTable中生成ObjectiveDetail 也继承或添加以下附加检查:if (entry.Entity is IAuditableTable) {以停止方法体运行。

我的问题是。为什么我需要将这个辅助检查添加到代码中以使其适用于我,是否有更好的方法可以使此代码仅适用于从IAuditableTable继承的类?如果我的类包含其他类而不是实现IAuditable的对象,那么e => e.Entity is IAuditableTable似乎不起作用。

这是我的代码:

foreach (var entry in this.ChangeTracker.Entries()
             .Where(
                  e => e.Entity is IAuditableTable &&
                 (e.State == EntityState.Added) ||
                 (e.State == EntityState.Modified)))
{
    // I do not know why the following line is needed. My code will not work
    // unless I have the following line for classes that contain classes that
    // do not inherit from IAuditableTable
    if (entry.Entity is IAuditableTable) {
        IAuditableTable e = (IAuditableTable)entry.Entity;
        if (entry.State == EntityState.Added)
        {
            if (e.CreatedBy == 0) 
                e.CreatedBy = 1;
            if (e.CreatedDate == DateTime.MinValue) 
                e.CreatedDate = DateTime.Now;
        }
        if (e.ModifiedBy == 0) 
            e.ModifiedBy = 1;
        if (e.ModifiedDate == DateTime.MinValue) 
            e.ModifiedDate = DateTime.Now;
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于运营商的默认优先顺序&amp;&amp;和||在where方法的条件下。

您目前拥有的条件有AND和OR条件,但您没有添加括号来解析运算符&amp;&amp;,||的方式将被解决:

this.ChangeTracker.Entries()
         .Where(
              e => e.Entity is IAuditableTable &&
             (e.State == EntityState.Added) ||
             (e.State == EntityState.Modified))

因此,默认情况下,它被解释为:

(e.Entity is IAuditableTable && (e.State == EntityState.Added))
|| (e.State == EntityState.Modified)

这将包括记录if(实体是IAuditable AND添加)还是被修改。因此,即使它不是IAuditableTable,如果实体被修改,它也将被包含在循环中。

对于您想要的逻辑,您需要添加包含||的括号检查实体的条件已添加或修改:

e.Entity is IAuditableTable && 
((e.State == EntityState.Added) || (e.State == EntityState.Modified))

这样,只有在IAuditable AND(被修改或添加)

时才会包含它