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 にする必要があります。

EDMX デザイナーで EF4 を使用してこれを達成するにはどうすればよいですか?

アップデート:

これは私が最終的に使用したものです:

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サーバー側ではなく、サービスサーバー側について話しています)

4

3 に答える 3

3

エンティティ タイプ名が 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はこれとは関係ありません。それらは、まったく異なる無関係なもののために存在します。

于 2010-10-12T19:15:30.843 に答える
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 に答える
0

個人的には、クライアント側のコードベースのソリューションが好きです。POCO を使用しているので、オブジェクト自体に更新を行わせるのがおそらく最も簡単でしょう。Name プロパティの set アクセサーを更新して、Modified プロパティと Revision プロパティを変更する "objectModified" メソッドを呼び出します。

プロパティが変更されてからオブジェクトが保存されるまでの時間差が原因でそれが受け入れられない場合は、Entities オブジェクトの部分クラスを利用できます。そうすることで、Entities オブジェクトの ObjectSet<T> プロパティでエンティティを操作できる SaveChanges メソッドをオーバーライドできます。何かのようなもの:

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 に答える