Технически вы могли бы представить интерфейс с явной реализацией, например:
In Contacts.Entities сборка:
public interface IContactsDbContext
{
IQueryable<Contact> Contacts { get; }
// Not DbSet<Contact> because you don't want dependency on EF assembly
}
//...
public class Contact : IValidatableObject // No partial class anymore
{
public string Name { get; set; }
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext)
{
IContactsDbContext context =
validationContext.Items["Context"] as IContactsDbContext;
if (context.Contacts.Any<Contact>(c => c.Name == this.Name))
yield return new ValidationResult(
"Contact 'Name' is already in use.", new string[] { "Name" });
yield break;
}
// IValidatableObject, ValidationResult and ValidationContext is in
// System.ComponentModel.DataAnnotations.dll, so no dependency on EF
}
In Contacts.Repository сборка (ссылки Contacts.Entities Assembly):
public class ContactsDbContext : DbContext, IContactsDbContext
{
public DbSet<Contact> Contacts { get; set; }
IQueryable<Contact> IContactsDbContext.Contacts // explicit impl.
{
get { return Contacts; } // works because DbSet is an IQueryable
}
protected override DbEntityValidationResult ValidateEntity(
DbEntityEntry entityEntry, IDictionary<object, object> items)
{
items.Add("Context", this);
return base.ValidateEntity(entityEntry, items);
}
}
Contacts.Validation сборка может быть удалена.
Однако мне не очень нравится это решение.Ваш POCO имеет - через метод Validate
- все еще зависимость от хранилища, если интерфейс или нет.Для более строгого разделения интересов я, вероятно, предпочел бы иметь отдельный класс проверки, который, возможно, также выполняет операции с репо.Или, если бы я реализовал IValidatableObject
, я бы, вероятно, делал только проверки, которые зависят только от свойств объекта модели (например, «дата производства не должна быть позже даты отгрузки» и т. Д.).Ну, это частично вопрос вкуса.Второй пример, который вы связали, на самом деле не заботится о разделении интересов, поэтому вы как-то конфликтуете с первым примером.