我有一个使用实体框架6的数据层
数据库优先
. 我的一个实体表示一个时间跨度——它有一个开始日期和一个结束日期。
public class Range
{
public Guid ID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
我想添加验证以确保
Range
S从来没有重叠的日期。将保存添加、修改和删除的应用程序
范围
马上就来。所以我在玩凌驾
ValidateEntity
在我的
DbContext
. 以下是我最后发现的问题:
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var result = new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
if (entityEntry.Entity is Range && (entityEntry.State == EntityState.Added || entityEntry.State == EntityState.Modified))
{
Range range = entityEntry.Entity as Range;
if (Ranges.Local.Any(p => range.EndDate >= p.StartDate && range.StartDate <= p.EndDate) ||
Ranges.Any(p => range.EndDate >= p.StartDate && range.StartDate <= p.EndDate))
{
result.ValidationErrors.Add(
new System.Data.Entity.Validation.DbValidationError("EndDate", "Cannot overlap another range.")); //Could be StartDate's fault but we just need save to fail
}
}
if (result.ValidationErrors.Count > 0)
{
return result;
}
else
{
return base.ValidateEntity(entityEntry, items);
}
}
问题是
Ranges.Local
不查询数据库和
Ranges
查询数据库的,不包括未保存的更改。
例如,如果在我的数据库中
范围
从9/1开始到9/8结束,然后在内存中我将其修改为从8/1开始到8/8结束,并且我还添加了一个新的
范围
从9/6开始到9/12结束,
Ranges.Any(p => blockOut.EndDate >= p.StartDate && blockOut.StartDate <= p.EndDate)
将为添加的返回true
范围
因为当前保存的
范围
重叠。但它实际上是有效的,因为在内存中,这些日期已经更改,并且在保存时不会有重叠。
是否有任何方法可以查询本地和数据库的组合。即只查询数据库中不在本地的记录?
编辑:
更新后的代码,我认为是对史蒂夫py的回答的回应:
//Check Local first because we may be able to invalidate without querying the DB
if (BlockOutPeriods.Local.Any(p => blockOut.ID != p.ID && blockOut.EndDate >= p.StartDate && blockOut.StartDate <= p.EndDate))
{
result.ValidationErrors.Add(
new System.Data.Entity.Validation.DbValidationError("EndDate",
"Block out cannot overlap another block out."));
}
else
{
var editedIDs = BlockOutPeriods.Local.Select(p => p.ID);
//!Contains avoids reading & mapping all records to Range model objects - better?
if (BlockOutPeriods.Any(p => blockOut.EndDate >= p.StartDate && blockOut.StartDate <= p.EndDate && !editedIDs.Contains(p.ID)))
{
result.ValidationErrors.Add(
new System.Data.Entity.Validation.DbValidationError("EndDate",
"Block out cannot overlap another block out."));
}
}