簡體   English   中英

如何在保存時自動更新Entity Framework 4中實體的Modified屬性?

[英]How to auto-update the Modified property on a Entity in Entity Framework 4 when saving?

我在VS2010,POCO和模型優先方法中使用EF4。

我的實體具有以下屬性:Id:Guid,Name:String,Created:DateTime,Modified:DateTime,Revision:Int32。

我創建我的實體,設置名稱並使用EF4上下文將其保存到數據庫。 這應該將Id設置為新的Guid(與Identity-SGP一起使用),Created設置為now,Modified left as 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仍然是未修改的。 我不懂這個......

為什么默認情況下不啟用更改跟蹤? 我使用自我跟蹤實體,為什么我要把它關閉並每次明確地打開它? 為什么即使狀態未經修改,實體仍然持有db? 那么EntityState和ObjectState之間的區別是什么? 目前我正在進行所有更改並更新服務器端,但我也將使用WCF服務來回傳輸實體一段時間......這里如何處理更改有什么不同? 如果服務器端的所有更改,無論是開啟/關閉更改,都會持續存在? 我想要的是,在沒有更新Modified,Revision等的情況下,任何東西都不能存儲。當收到對象並且已經更改時,應始終在服務器上設置這些屬性。 (我不是在這里討論sql-server-side而是服務端服務器端)

假設您的實體類型名稱是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++;
}


如果您希望使用此代碼為所有實體填充公共字段(如ModifiedDate或ModifiedBy),請查看此帖子:
實體框架 - 審計活動

順便說一句, StoreGeneratedPatternConcurrencyMode與此無關,它們存在於完全不同且不相關的內容中。

我們可以使用partial class並覆蓋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();
        }
    }
}

我個人偏愛基於客戶端代碼的解決方案。 由於您正在使用POCO,因此讓對象本身進行更新可能是最簡單的。 更新Name屬性上的set訪問器以調用更改Modified和Revision屬性的“objectModified”方法。

如果由於更改屬性的時間與保存對象的時間之間的時間差而導致這種情況不合適,則可以使用Entities對象上的分部類。 這樣做將允許您覆蓋SaveChanges方法,您可以在Entities對象的ObjectSet <T>屬性中觸摸您的entites。 就像是:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM