Это моя идеальная идея дня: сильные типизированные идентификаторы в Entity Framework.Тип безопасных ключей с моделью Entity Framework
Мотивация:
- Сравнение ModelTypeA.ID и ModelTypeB.ID (по крайней мере, почти) всегда ошибка. Почему не скомпилировать это?
- Если вы используете пример для запроса DbContext, его легко реализовать, получите непосредственно модель от id. "id.Value.ProductNumber"
- Код будет более само декларативным.
- Они просто естественно набраны так, почему бы и нет?
Хорошо, вот моя реализация. Я надеюсь, что его довольно само декларативный, что я имею в виду.
//Optional interface may be handy on some scenarios
public interface Identifiable<T> where T : class, Identifiable<T>
{
DbId<T> ID { get; set; }
}
public class TestModel1 : Identifiable<TestModel1>
{
[Key]
public DbId<TestModel1> ID { get; set; }
public string Data1 { get; set; }
}
public class TestModel2 : Identifiable<TestModel2>
{
[Key]
public DbId<TestModel2> ID { get; set; }
public string Data2 { get; set; }
public DbId<TestModel1> TestModel1ID { get; set; }
public virtual TestModel1 TestModel1 { get; set; }
}
[Serializable]
public class DbId<T> where T : class
{
public int ID { get; set; }
public static implicit operator DbId<T>(int id)
{
var c = new DbId<T>() { ID = id };
return c;
}
public static implicit operator int (DbId<T> id)
{
return id.ID;
}
}
При создании миграции его jus жалуются, что нет ключа. При попытке установить ключ на беглой api он дает более ценную ошибку: Идентификатор свойства не может быть использован как свойство ключа в сущности MyNs.Models.TestModel1, потому что тип свойства не является допустимым типом ключа. Поддерживаются только типы скалярных, строковых и байтовых [].
Хорошо понимаемый ключ не может быть ни одного типа, но данные моего типа - это всего лишь одна int witch, даже имеющая неявные преобразования. Наследование int в этой ситуации очень заманчиво, но, как мы знаем, это невозможно.
Основной вопрос: как закончить это и сказать EF, что преобразование моего DbId в int и обратно не является наукой о ракете.
Второй вопрос: Это хорошая идея? Зачем? Вы предлагаете запрос функции, если это невозможно в настоящее время?
Я понимаю, что вы пытаетесь сделать, но это ужасная работа, чтобы попытаться предотвратить то, что очень редко произойдет при аварии. Я полагался бы на тестирование уровня абстракции выше, а не на это. – viggity
Почему это ужасная работа? После того, как реализовано одно (и базовое решение уже есть), решение является переносимым/разделяемым, и только различие заключается в замене «int» на «DbId» при написании нового кода. –
user766304