【问题标题】:How to add C# automatic calculations for a POCO entity in EF?如何在 EF 中为 POCO 实体添加 C# 自动计算?
【发布时间】:2015-06-01 10:03:03
【问题描述】:

我使用 DB first EF 6.1.3 和 .NET 4.5.1,T4 生成的实体是具有生成的自动属性的 POCO 类。我想在保存到数据库之前做一些计算(实际上是一个计算的 int 字段)。

我当然可以使用 UPDATE 触发器来做到这一点,但现在我更喜欢 C# 算法。我已经在 DBContext 中寻找要覆盖的内容,但一无所获。最接近的赌注是ValidateEntity(...),但这闻起来让我用它的名字暗示完全不同的东西。 (不说怎么访问实体实例好像不是小事)

如何以及在何处完成更新前或更好的自动计算:根据属性设置?

【问题讨论】:

    标签: c# .net entity-framework


    【解决方案1】:

    您可以执行以下操作,即覆盖 SaveChanges。

    public partial class MyEntities : ObjectContext
    {
        /// <summary>
        /// Persists all updates to the data source with the specified System.Data.Objects.SaveOptions.
        /// </summary>
        /// <param name="saveOptions">A System.Data.Objects.SaveOptions value that determines the behavior of the operation.</param>
        /// <returns>The number of objects in an System.Data.EntityState.Added, System.Data.EntityState.Modified, or 
        /// System.Data.EntityState.Deleted state when System.Data.Objects.ObjectContext.SaveChanges() was called.</returns>
        public override int SaveChanges(SaveOptions saveOptions)
        {
            List<Itinerary> itineraryLocations = ItineraryAddedDeletedMonitor.GetItineraryLocations(this);
    
            AlertManager.ObjectContextSavingChanges(this, null);
            int changes = base.SaveChanges(saveOptions);
    
            if (ItineraryAddedDeletedMonitor.ProcessItineraryLocations(this, itineraryLocations))
            {
                // new rows have been added
                base.SaveChanges(saveOptions);
            }
    
            return changes;
        }
    }
    

    更新:

    为了访问实体实例,下例中的 objectStateEntries 获取所有已修改、添加和删除的实体(根据需要进行更改):

    IEnumerable<ObjectStateEntry> objectStateEntries = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added | EntityState.Deleted);
    
    foreach (ObjectStateEntry entry in objectStateEntries)
    {
        if (!entry.IsRelationship && entry.Entity.GetType() == typeof(CustomerTransfer) && entry.State == EntityState.Deleted)
        {
            // Do some magic if the entity type is a CustomerTransfer that has been deleted.
        }
    }
    

    更新:

    ... 变量 objectContext 是:

    var objectContext = ((IObjectContextAdapter)this).ObjectContext;
    

    【讨论】:

    • Paul,如何获取更新下的实体实例?
    【解决方案2】:

    例如,您有一个用户,该用户首先使用数据库生成了自动属性。在您的 .tt 文件中将生成一个 User.cs 文件。这些是生成的,因此没有必要更改它们

    你可以做的是创建一个新文件来包含元数据类,在这个例子中我将它命名为 EntityAnnotations.cs,我之所以称之为它,是因为你也可以使用它来为你的实体属性添加注释。

    如果用户生成的类(从您现有的数据库生成)有

     public partial class User
     {   
         public int UserId { get; set; }
         public string UserName { get; set; }
         public string EmailAddress { get; set; }
         public int CalculatedValue {get;set;}
     }
    

    你可以创建这个

    [MetadataType(typeof(UserMetadata))]
    public partial class User
    {
         public int Calculate
         {
            get { return CalculatedValue;}
            set { CalculatedValue = value +1;}
         }
    }
    

    然后

    public class UserMetadata
    {
        //Fields from User requiring annotations
        [EmailAddress]
        public string EmailAddress { get; set; }   
    }
    

    我现在已使用元数据对生成的实体强制执行电子邮件地址验证。我还使用部分类添加了一个Calculate 字段,它将从get 上的生成类返回CalculatedValue 属性,并将calculatedValue 属性设置为Calculateset 逻辑的结果

    【讨论】:

    • James,计算的属性(Calculated)是否存储在 DB 中?
    • 在上面的例子中,没有。因为您首先使用数据库。您可以在 DB 上创建字段,更新 EDMX,然后它将出现在生成的类中。然后您在 EntityAnnotations.cs 中创建的部分可以处理计算。我会更新示例
    • 如果字段在edmx中,那么属性会自动为它生成,也不可能创建自定义getter...
    • 有,你创建另一个部分类如上所示。您可以选择不返回数据库值并完全返回其他内容,您可以在自定义 getter 中执行此操作。我同意一个不会有很多用途,但它可以创建
    • James,在您的示例代码中,您在未生成的部分类中复制了 Calculated 属性,这显然是一个编译错误......此外,问题中的规范非常清楚,并在我的 prev 中进一步解释评论:我需要在数据库中存储一个计算字段(就像更新触发器一样),我想用 C# 在客户端进行计算
    【解决方案3】:

    您可以使用the SavingChanges event。如果您使用此技术,您可以查找所需类型和处于所需状态的实体来修改它们。文档上的示例显示了如何找到这些实体。

    【讨论】:

      猜你喜欢
      • 2012-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多