Мы работаем с довольно большой моделью в первой настройке кода EF 6.1, и мы используем int для идентификаторов сущностей.
К сожалению, это не так, как хотелось бы, так как мы можем легко смешивать идентификаторы, например, сравнивая идентификаторы объектов разных типов (myblog.Id == somePost.Id) или аналогичные. Или еще хуже: myBlog.Id ++.
Поэтому я придумал идею использования типизированных идентификаторов, поэтому вы не можете смешивать идентификаторы. Поэтому нам нужен тип BlogId для нашего блога. Теперь очевидным выбором было бы использовать int, завернутый в структуру, но вы не можете использовать structs как ключи. И вы не можете расширить int... - подождите, вы можете! Использование enum!
Итак, я придумал это:
public enum BlogId : int { }
public class Blog
{
public Blog() { Posts = new List<Post>(); }
public BlogId BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
internal class BlogConfiguration : EntityTypeConfiguration<Blog>
{
internal BlogConfiguration()
{
HasKey(b => b.BlogId);
Property(b=>b.BlogId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
Итак, теперь у нас есть типы safeID - сравнение BlogId и PostId - это ошибка времени компиляции. И мы не можем добавить 3 в BlogId. Пустые перечисления могут выглядеть немного странно, но это больше детализация реализации. И мы должны установить параметр DatabaseGeneratedOption.Identity явно в нашем сопоставлении, но это одноразовое усилие.
Прежде чем мы начнем преобразовывать весь наш код в этот шаблон, существуют ли очевидные проблемы?
Изменить: Вероятно, мне нужно выяснить, почему мы должны работать с идентификаторами вместо полных объектов. Иногда нам нужно сопоставлять объекты в запросах EF Linq - и сравнение объектов там не работает. Например (построив пример блога и предположив несколько более богатую модель домена): найдите комментарии к записи в текущем блоге пользователей. Помните, что мы хотим сделать это в базе данных (у нас много данных), и мы предполагаем, что нет прямых навигационных свойств. И currentUser не подключен. Наивный подход был бы
from c in ctx.Comments where c.ParentPost.Blog.Author == currentUser
Это не работает, поскольку вы не можете сравнивать объекты в EF Linq. Поэтому мы стараемся
from c in ctx.Comments where c.ParentPost.Blog.Id == currentUser.Id
Это компилируется и выполняется, но не так - должно быть
from c in ctx.Comments where c.ParentPost.Blog.Author.Id == currentUser.Id
Элементы safeafe поймали бы его. И у нас есть гораздо более сложные запросы, чем это. Попробуйте "найти комментарии к записи в текущие пользователи, сделанные конкретным другим пользователем, которые текущий пользователь не прокомментировал позже".
С уважением, Нильс