6

我在 VS2010、POCO 和模型优先方法中使用 EF4。

我的实体具有以下属性:Id:Guid、Name:String、Created:DateTime、Modified:DateTime、Revision:Int32。

我创建我的实体,设置名称并使用 EF4 上下文将其保存到数据库中。这应该将 Id 设置为新的 Guid(与 Identity-SGP 一起使用),Created 设置为 now,Modified 保留为 null,Revision 设置为 0。我检索实体,更改名称并再次保存。这次 Modified-value 应该设置为 now 并且 revision 应该是 1。

如何使用 EF4 和 EDMX 设计器最好地完成此任务?

更新:

这就是我最终使用的:

public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
    foreach (ObjectStateEntry entry in ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Where(e => e.Entity is EntityBase))
    {
        EntityBase entity = entry.Entity as EntityBase;
        if (entry.State == EntityState.Added)
        {
            entity.Version = new Version() { Major = 1, Minor = 0, Revision = 0 };
            entity.Created = DateTime.Now;
            if (OperationContext.Current != null) entity.CreatedBy = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name;
        }
        else if (entry.State == EntityState.Modified)
        {
            entity.Version.Revision++;
            entity.Modified = DateTime.Now;
            if (OperationContext.Current != null) entity.ModifiedBy = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name;
        }
    }

    return base.SaveChanges(options);
}

哪个不起作用... :(

问题是即使我显式运行 MarkAsModified() 方法,entry.State 仍然未修改。我不明白这个...

为什么默认不启用更改跟踪?我使用自我跟踪实体,为什么我要关闭它并每次都明确打开它?为什么即使状态未修改,实体也会持久化到数据库?EntityState 和 ObjectState 有什么区别?目前,我在服务器端进行所有更改和更新,但一段时间后我还将使用 WCF 服务来回传输实体......这里如何处理更改有区别吗?如果服务器端的所有更改,无论更改跟踪开/关,都保持不变?我想要的是,如果不更新 Modified、Revision 等,任何东西都不应该被存储。当对象被接收回来并发生变化时,这些属性应该始终在服务器上设置。(我不是在说 sql-server-side 而是在 service-server-side)

4

3 回答 3

3

假设您的实体类型名称是产品:

partial void OnContextCreated() {
    this.SavingChanges += Context_SavingChanges;
}

void Context_SavingChanges(object sender, EventArgs e) {

    IEnumerable objectStateEntries =
            from ose
            in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | 
                                                            EntityState.Modified)
            where ose.Entity is Product
            select ose;

    Product product = objectStateEntries.Single().Entity as Product;

    product.ModifiedDate = DateTime.Now;
    product.ComplexProperty.Revision++;
}


如果您希望使用此代码为您的所有实体填充公共字段,例如 ModifiedDate 或 ModifiedBy,请查看这篇文章:
Entity Framework - Auditing Activity

顺便说一下,StoreGeneratedPatternConcurrencyMode与此无关,他们在那里是为了完全不同和不相关的东西。

于 2010-10-12T19:15:30.843 回答
0

我个人偏爱基于客户端代码的解决方案。由于您使用的是 POCO,因此让对象本身进行更新可能是最简单的。更新 Name 属性上的 set 访问器以调用更改 Modified 和 Revision 属性的“objectModified”方法。

如果由于更改属性的时间和保存对象的时间之间的时间差而使这令人不快,您可以利用实体​​对象上的部分类。这样做将允许您覆盖 SaveChanges 方法,您可以在其中触摸实体对象上的 ObjectSet<T> 属性中的实体。就像是:

public partial class YourEntities
{
    public override int SaveChanges(System.Data.Objects.SaveOptions options)
    {
        //update your objects here
        return base.SaveChanges(options);
    }
}
于 2010-10-12T19:45:23.653 回答
0

我们可以使用部分类并重写 SaveChanges 方法来实现这一点。

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;


namespace TestDatamodel
{
    public partial class DiagnosisPrescriptionManagementEntities
    {
        public override int SaveChanges()
        {
            ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;

            foreach (ObjectStateEntry entry in
                     (context.ObjectStateManager
                       .GetObjectStateEntries(EntityState.Added | EntityState.Modified)))
            {                    
                if (!entry.IsRelationship)
                {
                    CurrentValueRecord entryValues = entry.CurrentValues;
                    if (entryValues.GetOrdinal("ModifiedBy") > 0)
                    {
                        HttpContext currentContext = HttpContext.Current;
                        string userId = "nazrul";
                        DateTime now = DateTime.Now;

                        if (currContext.User.Identity.IsAuthenticated)
                        {
                            if (currentContext .Session["userId"] != null)
                            {
                                userId = (string)currentContext .Session["userId"];
                            }
                            else
                            {                                    
                                userId = UserAuthentication.GetUserId(currentContext .User.Identity.UserCode);
                            }
                        }

                        if (entry.State == EntityState.Modified)
                        {
                           entryValues.SetString(entryValues.GetOrdinal("ModifiedBy"), userId);
                           entryValues.SetDateTime(entryValues.GetOrdinal("ModifiedDate"), now);
                        }

                        if (entry.State == EntityState.Added)
                        {
                            entryValues.SetString(entryValues.GetOrdinal("CreatedBy"), userId);
                            entryValues.SetDateTime(entryValues.GetOrdinal("CreatedDate"), now);
                        }
                    }
                }
            }

            return base.SaveChanges();
        }
    }
}
于 2014-09-18T09:07:56.410 回答