這可能是一個簡單的問題,但是我是Code First和Migrations的新手,因此需要我。我會繼續示例代碼到最低限度,藉以說明問題:製作AddOrUpdate僅更改一些屬性
我有一個BaseAuditableEntity
,其中包括本(除其他事項外,但讓我們簡化):
public abstract class BaseAuditableEntity : BaseEntity, IAuditableEntity
{
public DateTime CreatedOn { get; set; }
public DateTime LastModified { get; set; }
}
現在,(例如)User
POCO從它繼承:
public class User : BaseAuditableEntity
{
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public bool Active { get; set; }
public DateTime? LastLogin { get; set; }
}
我有這個在我的上下文的SaveChanges
方法,填補了CreatedOn
和LastModified
日期(簡體):
public override int SaveChanges()
{
var changeSet = ChangeTracker.Entries<IAuditableEntity>();
if (changeSet != null)
{
foreach (var entry in changeSet.Where(p => p.State != EntityState.Unchanged))
{
var now = DateTime.UtcNow;
if (entry.State == EntityState.Added)
entry.Entity.CreatedOn = now;
entry.Entity.LastModified = now;
}
}
return base.SaveChanges();
}
現在我有地方種子一些用戶來說,這樣的遷移:
protected override void Seed(MyContext context)
{
context.Users.AddOrUpdate(
p => p.UserName,
new User { Active = true,
FullName = "My user name",
UserName = "ThisUser",
PasswordHash = "",
Email = "[email protected]",
LastLogin = null,
}
// etc.
);
}
現在我有播種有問題,在遷移之後AddOrUpdate
。當實體是新的時候(它被添加),CreatedOn
被正確填充並且一切按預期工作。但是,當實體被修改時(它已經存在於數據庫和UserName
匹配項中),它會嘗試使用我正在創建的新實體更新它...因爲CreatedOn
的DateTime
(本例中爲DateTime.MinValue
)的值無效。
有什麼方法可以使用AddOrUpdate
方法,以便它實際上從數據庫中檢索匹配的實體並更新非默認字段?或者,也許某種方式來告訴它哪些字段不更新?對於這種特定情況,我希望CreatedOn
字段保持不變,但一般的解決方案將不勝感激。
也許我應該做我自己的AddOrUpdate
方法,其中包括一個謂詞與我想改變的領域,而不是傳遞一個全新的實體?
這是EF 6.1
更新
我知道我可以很容易地解決這個爲CreatedOn
日期,這是目前我在做什麼,這種特定的情況:
foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged))
{
var now = DateTime.UtcNow;
if (entry.State == EntityState.Added)
{
entry.Entity.CreatedOn = now;
}
else
{
if (entry.Property(p => p.CreatedOn).CurrentValue == DateTime.MinValue)
{
var original = entry.Property(p => p.CreatedOn).OriginalValue;
entry.Property(p => p.CreatedOn).CurrentValue = original != SqlDateTime.MinValue ? original : now;
entry.Property(p => p.CreatedOn).IsModified = true;
}
}
entry.Entity.LastModified = now;
}
我我正在尋找更通用的解決方案
謝謝你的'Upsert'方法工作的很好,這正是我所期待的! – Jcl 2014-09-19 10:02:51
我已經修改了更新,以便它檢查屬性的值不是相同的值(對於基元/值/字符串類型),所以如果它們的值相同,並且它們不會將實體標記爲「已修改」 Unchanged'。爲了播種的目的,我相信這會更好。 在我的問題的具體情況下,這使得它始終不修改'LastModified' – Jcl 2014-09-19 11:06:24
@JCL,你是對的,這可以防止不必要的更新。我相應地更新了答案 – 2014-09-19 11:56:56