Еще один способ подумать о unzip
или transpose
- преобразовать список строк в список столбцов.
pitchers = [('Nolan', 'Ryan'), ('Roger', 'Clements'), ('Schilling','Curt')]
first_names, last_names = zip(*pitchers)
In [45]: first_names
Out[45]: ('Nolan', 'Roger', 'Schilling')
In [46]: last_names
Out[46]: ('Ryan', 'Clements', 'Curt')
Поскольку у меня есть сервисный уровень, посредник между моими контроллерами (im using ASP.NET MVC) и мой репозиторий, я решил автоматически установить поля здесь.
Кроме того, у моих POCO нет отношений / абстракций, они полностью независимы. Я хотел бы сохранить его таким образом, а не отмечать какие-либо виртуальные свойства или создавать базовые классы.
Итак, я создал интерфейс IAutoGenerateDateFields:
public interface IAutoGenerateDateFields
{
DateTime LastModified { get;set; }
DateTime CreatedOn { get;set; }
}
Для любого POCO i хотите автоматически сгенерировать эти поля, я реализую эту интуицию.
Используя пример в моем вопросе:
public class PocoWithDates : IAutoGenerateDateFields
{
public string PocoName { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime LastModified { get; set; }
}
На моем сервисном уровне я теперь проверяю, реализует ли конкретный объект интерфейс:
public void Add(SomePoco poco)
{
var autoDateFieldsPoco = poco as IAutoGenerateDateFields; // returns null if it's not.
if (autoDateFieldsPoco != null) // if it implements interface
{
autoDateFieldsPoco.LastModified = DateTime.Now;
autoDateFieldsPoco.CreatedOn = DateTime.Now;
}
// ..go on about other persistence work.
}
Я, скорее всего, сломаю этот код в дополнении к методу помощника / расширения позже.
Но я думаю, что это достойное решение для моего сценария , так как я не хочу использовать виртуальные машины в Save (поскольку я использую Unit of Work, Repository и Pure POCO) и не хочу использовать триггеры.
Если у вас есть мысли / предложения, дайте мне знать.
должен был добавить базовый объект, расширить его из первой частичной базы данных (что не является идеальным)
public override int SaveChanges()
{
AddTimestamps();
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync()
{
AddTimestamps();
return await base.SaveChangesAsync();
}
private void AddTimestamps()
{
//var entities = ChangeTracker.Entries().Where(x => x.Entity is BaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));
//ObjectiveContext context = ((IObjectContextAdapter)this).ObjectContext;
var entities = ChangeTracker.Entries().Where(e => e.Entity is BaseEntity && (e.State == EntityState.Modified || e.State == EntityState.Added)).ToList();
var currentUsername = !string.IsNullOrEmpty(System.Web.HttpContext.Current?.User?.Identity?.Name)
? HttpContext.Current.User.Identity.Name
: "Anonymous";
foreach (var entity in entities)
{
if (entity.State == EntityState.Added)
{
((BaseEntity)entity.Entity).CREATEDON = DateTime.UtcNow;
((BaseEntity)entity.Entity).CREATEDBY = currentUsername;
}
((BaseEntity)entity.Entity).MODIFIEDON = DateTime.UtcNow;
((BaseEntity)entity.Entity).MODIFIEDBY = currentUsername;
}
}
Я также хотел бы предложить последнее решение. Это применимо только к .NET Framework 4, но делает эту задачу тривиальной.
var vs = oceContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
foreach (var v in vs)
{
dynamic dv = v.Entity;
dv.DateLastEdit = DateTime.Now;
}
У вас есть два варианта:
poco.LastModified = DateTime.Now;
в виртуальном .Save()
методе, который всем остальным придется называть Я не думаю, что есть какой-либо другой разумно безопасный и простой способ для достижения этого.
Для достижения этого мы можем использовать метод partial и переопределить метод 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();
}
}
}
Я знаю, что немного опаздываю на вечеринку, но я просто решил это для проекта, над которым я работаю, и решил поделиться своим решением.
Во-первых, чтобы сделать решение более re-usable, я создал базовый класс со свойствами timestamp:
public class EntityBase
{
public DateTime? CreatedDate { get; set; }
public DateTime? LastModifiedDate { get; set; }
}
Затем я переопределил метод SaveChanges в моем DbContext:
public class MyContext : DbContext
{
public override int SaveChanges()
{
ObjectContext context = ((IObjectContextAdapter)this).ObjectContext;
//Find all Entities that are Added/Modified that inherit from my EntityBase
IEnumerable<ObjectStateEntry> objectStateEntries =
from e in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
where
e.IsRelationship == false &&
e.Entity != null &&
typeof(EntityBase).IsAssignableFrom(e.Entity.GetType())
select e;
var currentTime = DateTime.Now;
foreach (var entry in objectStateEntries)
{
var entityBase = entry.Entity as EntityBase;
if (entry.State == EntityState.Added)
{
entityBase.CreatedDate = currentTime;
}
entityBase.LastModifiedDate = currentTime;
}
return base.SaveChanges();
}
}
SaveChangesAsync
. Например. public override Task<int> SaveChangesAsync() { /* do something */ return base.SaveChangesAsync(); }
– Shaun Luttin
17 February 2014 в 10:45
здесь отредактирована версия предыдущего ответа. Предыдущая версия для меня не работала.
public override int SaveChanges()
{
var objectStateEntries = ChangeTracker.Entries()
.Where(e => e.Entity is TrackedEntityBase && (e.State == EntityState.Modified || e.State == EntityState.Added)).ToList();
var currentTime = DateTime.UtcNow;
foreach (var entry in objectStateEntries)
{
var entityBase = entry.Entity as TrackedEntityBase;
if (entityBase == null) continue;
if (entry.State == EntityState.Added)
{
entityBase.CreatedDate = currentTime;
}
entityBase.LastModifiedDate = currentTime;
}
return base.SaveChanges();
}