如何在保存时自动更新 Entity Framework 4 中实体的 Modified 属性?

发布于 2024-09-27 07:48:37 字数 1728 浏览 3 评论 0原文

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

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

我创建实体、设置名称并使用 EF4 上下文将其保存到数据库中。这应该将 Id 设置为新的 Guid(与 Identity-SGP 一起使用),将“创建”设置为“现在”,将“修改”保留为空,将“修订”设置为 0。我检索实体,更改名称并再次保存。这次修改值应设置为 now,修订版应为 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 服务来回传输实体...如果在服务器端,这里处理更改的方式有什么不同吗?所有更改,无论更改跟踪打开/关闭,都会被保留?我想要的是,如果不更新修改、修订等,则任何内容都不应被存储。当接收回对象时,应始终在服务器上设置这些属性并且已经改变了。(我这里说的不是 sql 服务器端,而是服务服务器端)

Im using EF4 in VS2010, POCO's and the model-first approach.

My entity has the following properties: Id:Guid, Name:String, Created:DateTime, Modified:DateTime, Revision:Int32.

I create my entity, set the name and save it to the database using the EF4-context. This should set Id to a new Guid (works with Identity-SGP), Created set to now, Modified left as null, Revision set to 0. I retrieve the entity, change the name and save it again. This time the Modified-value should be set to now and revision should be 1.

How do I best accomplish this using EF4 with the EDMX-designer?

Update:

This was what I ended up using:

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);
}

Which isnt working... :(

The problem is that the entry.State is still unmodified even if I explicitly run the MarkAsModified()-method. I dont get this...

Why isnt change-tracking enabled by default? Im using self-tracking entities so why would I want it off and explicitly turn it on everytime? And why is entities persisted to db even if state is unmodified? And whats the difference between EntityState and ObjectState? At the moment Im making all changes and updates serverside but I will also use a WCF-service to transfer entities back and forth some time later... Is there a difference in how changes are treated here? If serverside all changes, no matter changetracking on/off, is persisted?? What I want is that nothing should ever be able to be stored without also updating Modified, Revision etc. These properties should always be set on the server when the object is received back and has changed. (Im not talking sql-server-side here but service-server-side)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

假扮的天使 2024-10-04 07:48:37

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

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),请查看这篇文章:

实体框架 - 审核活动

顺便说一下,StoreGeneratePattern 和 ConcurrencyMode 与此无关,它们用于完全不同且不相关的东西。

Let's assume your Entity Type name is Product:

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++;
}

If you are looking to use this code for populating common field such as ModifiedDate or ModifiedBy for all of your entities then please take a look at this post:

Entity Framework - Auditing Activity

By the way, StoreGeneratedPattern and ConcurrencyMode has nothing to do with this, they are there for completely different and unrelated stuff.

孤单情人 2024-10-04 07:48:37

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

如果由于属性更改时间和对象保存时间之间的时间差而导致这种情况令人不快,您可以利用实体​​对象上的分部类。这样做将允许您重写 SaveChanges 方法,您可以在其中触摸 ObjectSet中的实体。实体对象上的属性。像这样的东西:

public partial class YourEntities
{
    public override int SaveChanges(System.Data.Objects.SaveOptions options)
    {
        //update your objects here
        return base.SaveChanges(options);
    }
}

I'm partial to a client-side code-based solution, personally. Since you're using POCOs, it'd probably be simplest to have the object itself do the updating. Update the set accessor on the Name property to call an "objectModified" method that changes the Modified and Revision properties.

If that's unpalatable due to the time difference between the time the property is changed and the time the object is saved, you can tap into the partial class on your Entities object. Doing so will allow you to override the SaveChanges method where you can touch your entites in their ObjectSet<T> property on the Entities object. Something like:

public partial class YourEntities
{
    public override int SaveChanges(System.Data.Objects.SaveOptions options)
    {
        //update your objects here
        return base.SaveChanges(options);
    }
}
苏别ゝ 2024-10-04 07:48:37

我们可以使用分部类并重写 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();
        }
    }
}

We can use partial class and override SaveChanges method to achieve this.

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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文