У меня есть слой данных, использующий Entity Framework 6 База данных сначала .Одна из моих сущностей представляет промежуток времени - у него есть дата начала и дата окончания.
public class Range
{
public Guid ID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
Я хочу добавить проверку, которая гарантирует, что у Range
s никогда не будет перекрывающихся дат.Приложение будет сохранять добавленные, измененные и удаленные 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
, который запрашивает базу данных, не включаетнесохраненные изменения.
EG Если в моей базе данных у меня есть Range
, начиная с 9/1 и заканчивая 9/8, то в памяти я изменил его, чтобы он начинался 8/1 и заканчивался 8/8, и у меня естьтакже добавлен новый Range
, начиная с 9/6 и заканчивая 9/12, Ranges.Any(p => blockOut.EndDate >= p.StartDate && blockOut.StartDate <= p.EndDate)
вернет true для добавленного Range
, потому что текущий сохраненный Range
перекрывается.Но это действительно допустимо, потому что в памяти эти даты были изменены, и при сохранении не будет совпадений.
Есть ли способ запросить комбинацию Local и базы данных.IE только запрашивает базу данных для записей, которые не находятся в Local?
EDIT:
Обновленный код, который, я думаю, работает в ответ на ответ Стива Пи ниже:
//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."));
}
}