Как автоматически обновить свойство Modified для Entity в Entity Framework 4 при сохранении? - PullRequest
6 голосов
/ 12 октября 2010

Я использую EF4 в VS2010, POCO и подход, основанный на модели.

Моя сущность имеет следующие свойства: Id: Guid, Имя: String, Создано: DateTime, Изменено: DateTime, Редакция: Int32.

Я создаю свою сущность, задаю имя и сохраняю его в базе данных, используя EF4-контекст.Это должно установить Id для нового Guid (работает с Identity-SGP), созданный установленный в настоящее время, измененный оставленный как ноль, Revision, установленный в 0. Я получаю объект, изменяю имя и сохраняю его снова.На этот раз значение Modified должно быть установлено сейчас, а ревизия должна быть 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 (). Я не получаю этого ...

Почему отслеживание изменений не включено по умолчанию? Я использую объекты самоконтроля, так почему я хочу его отключить и явно отключить егона каждый раз? И почему сущности сохраняются в БД, даже если состояние не изменено? И в чем разница между EntityState и ObjectState? В настоящий момент я делаю все изменения и обновления на стороне сервера, но я также буду использовать WCF-сервис для передачи сущностей туда и обратноНекоторое время спустя ... Есть ли разница в том, как здесь обрабатываются изменения? Если на стороне сервера все изменения, независимо от того, включено или выключено отслеживание изменений, сохраняются? Я хочу, чтобы ничего не происходило.когда-либо сможет храниться без обновления Modified, Revision и т. д. Эти свойства всегда должны быть установлены на сервере, когда объект получен и изменен.(Я говорю здесь не о стороне сервера sql, а о стороне сервера обслуживания)

Ответы [ 3 ]

3 голосов
/ 12 октября 2010

Предположим, что ваше имя типа сущности равно 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, для всех ваших сущностей, тогда, пожалуйста,посмотрите на это сообщение:
Entity Framework - Auditing Activity

Кстати, StoreGeneratedPattern и ConcurrencyMode не имеет к этому никакого отношения, они там для совершенно разных и не связанных вещей.

0 голосов
/ 18 сентября 2014

Мы можем использовать частичный класс и переопределить метод 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();
        }
    }
}
0 голосов
/ 12 октября 2010

Лично я неравнодушен к клиентскому решению на основе кода.Поскольку вы используете POCO, вероятно, было бы проще, чтобы сам объект выполнял обновление.Обновите средство доступа set для свойства Name, чтобы оно вызывало метод «objectModified», который изменяет свойства Modified и Revision.

Если это неприятно из-за разницы во времени между временем изменения свойства и временем, в течение которого объектсохраненный, вы можете нажать на частичный класс на вашем объекте сущностей.Это позволит вам переопределить метод SaveChanges, где вы можете прикоснуться к своим объектам в их свойстве ObjectSet объекта Entities.Что-то вроде:

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