Как автоматически обновлять измененное свойство объекта в Entity Framework 4 при сохранении?
Im, используя EF4 в VS2010, POCO и первый подход модели.
моя сущность имеет следующие свойства: Id:Guid, Name:String, Created:DateTime, Modified:DateTime, Revision: Int32.
Я создаю свою сущность, устанавливаю имя и сохраняю его в базе данных с помощью EF4-контекста. Это должно установить Id в новый Guid (работает с Identity-SGP), созданный в настоящее время, измененный слева как null, ревизия установлена в 0. Я извлекаю сущность, меняю имя и сохраняю его снова. Эта пора измененное значение должно быть установлено в now и revision должно быть 1.
Как лучше всего выполнить это с помощью EF4 с помощью EDMX-designer?
обновление:
Это было то, что я в конечном итоге с помощью:
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 () -. Я не понимаю...
почему по умолчанию не включено отслеживание изменений? Im, используя сущностей с самостоятельным отслеживанием, так почему бы мне его и явно включить его каждый раз? И почему сущности сохраняются в БД, даже если состояние не изменяется? И в чем разница между EntityState и ObjectState? На данный момент я делаю все изменения и обновления на сервере, но я также буду использовать WCF-сервис для передачи сущностей назад и вперед некоторое время спустя... Есть ли разница в том, как здесь рассматриваются изменения? Если на сервере все изменения, независимо от "отслеживание изменений" вкл/выкл, является настаивал?? Я хочу, чтобы ничто никогда не могло храниться без обновления, изменения и т. д. Эти свойства всегда должны быть установлены на сервере, когда объект получен обратно и изменен. (Я не говорю sql-server-side здесь, но service-server-side)
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 для всех ваших объектов, пожалуйста, взгляните на этот пост:
Entity Framework-Аудиторская Деятельность
Кстати, StoreGeneratedPattern и значения concurrencymode не имеет ничего общего с этим, они существуют для совершенно разные и несвязанные вещи.
Я лично неравнодушен к решению на основе кода на стороне клиента. Поскольку вы используете POCOs, вероятно, было бы проще, чтобы сам объект выполнял обновление. Обновите метод доступа set для свойства Name, чтобы вызвать метод "objectModified", который изменяет свойства Modified и Revision.
Если это неприятно из-за разницы во времени между временем изменения свойства и временем сохранения объекта, вы можете нажать на частичный класс объекта Entities. Это позволит вам переопределить метод SaveChanges, где вы можете коснуться своих entites в свойстве ObjectSet
public partial class YourEntities
{
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
//update your objects here
return base.SaveChanges(options);
}
}
мы можем использовать частичный класс и переопределить метод 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();
}
}
}