В настоящее время я пытаюсь интегрировать приложение Entity Framework с устаревшей базой данных, возраст которой составляет около десяти лет. Одна из многих проблем, с которыми связана эта база данных (наряду с отсутствием каких-либо отношений или ограничений) состоит в том, что почти каждый столбец имеет значение null, хотя почти во всех случаях это не имеет смысла.Прозрачное преобразование значений с нулевым значением в значения, не допускающие нулевое значение в Entity Framework
Неизменно, я столкнусь исключение вдоль этих линий:
Свойства «SortOrder» на «MyRecord» не может быть установлен в «нулевую» стоимость. Вы должны установить это свойство в ненулевое значение типа 'Int32'.
Я видел много вопросов, относящихся к приведенному выше исключению, но все это кажется подлинными ошибками, когда разработчик не писал классы, которые должным образом представляют данные в базе данных. Я хотел бы преднамеренно написать класс, который неправильно отражает данные в базе данных. Я полностью осознаю, что это противоречит правилам Entity Framework, и это, скорее всего, связано с тем, что у меня так много трудностей.
Невозможно изменить схему в этот момент, так как она нарушит существующие приложения. Также невозможно зафиксировать данные, поскольку новые данные будут вставлены старыми приложениями. Я хотел бы сопоставить базу данных с Entity Framework, как и должно быть, медленно перемещать все приложения в течение ближайших нескольких лет или около того, чтобы полагаться на нее для доступа к данным, прежде чем, наконец, сможет перейти к этапу редизайна базы данных.
Один метод, который я использовал, чтобы обойти это прозрачно прокси-переменная:
internal int? SortOrderInternal { get; set; }
public int SortOrder
{
get { return this.SortOrderInternal ?? 0; }
set { this.SortOrderInternal = value; }
}
можно затем отобразить поле в CodeFirst:
entity.Ignore(model => model.SortOrder);
entity.Property(model => model.SortOrderInternal).HasColumnName("SortOrder");
Использование internal
ключевое слово в этом методе позволяет мне красиво инкапсулировать эту гадость, чтобы я мог, по крайней мере, не просачиваться за пределы моей сборки доступа к данным.
Но, к сожалению, я сейчас не в состоянии использовать прокси-поле в запросе как NotSupportedException
будет выброшено:
Указанный элемент типа «SortOrder» не поддерживается в LINQ к Entities. Поддерживаются только инициализаторы, сущности и свойства навигации сущности.
Возможно, возможно было бы прозрачно переписать выражение, если оно получено DbSet? Мне было бы интересно услышать, будет ли это работать; Я недостаточно разбираюсь в деревьях выражений. Я до сих пор не увенчался успехом в поиске метода в DbSet, который мог бы переопределить, чтобы манипулировать выражением, но я не над созданием нового класса, который реализует IDbSet и проходит через DbSet, хотя это ужасно.
При исследовании трассировки стека я нашел ссылку на внутреннюю концепцию платформы Entity Framework, называемую Shaper, которая, как представляется, является той, которая берет данные и вводит их в бит. Быстрый бит Googling по этой концепции не дает ничего, но исследование System.Data.Entity.dll с помощью dotPeek указывает на то, что это, безусловно, было бы чем-то, что помогло бы мне ... при условии, что Shaper<T>
не был внутренним и запечатанным. Я почти наверняка лаем на неправильное дерево здесь, но мне было бы интересно услышать, если кто-то столкнулся с этим раньше.
Есть ли причина, по которой вы не хотите работать с нулевыми свойствами? Это немного похоже на то, что вы пытаетесь «сражаться» с схемой базы данных, а не принимать ее ограничения и записывать свой код соответственно. –
Из интереса, почему бы вам просто не сделать свойства объекта null = false в свойствах CSDL/model. Хотя базовый SSDL имеет значение NULL, он корректно отображает непустые значения, но если значение null в БД будет изменено, вам нужно обработать исключение ConstraintException (свойство XXX в yyy не может быть установлено в свойство null) – StuartLC
@ AndrewStephens Я не хочу этого делать, потому что не следует создавать базу данных. Например, существует также ситуация, когда два разных объекта хранятся в одной таблице, которые я решил с помощью Entity Framework. Я хотел бы повторно интерпретировать данные на прикладном уровне, а затем в будущем, исправить базу данных, когда это возможно. Если я допустил значения NULL в классах на уровне Entity Framework (и это было бы почти все поля, даже внешние ключи), я не решаю эту проблему. –