2

В настоящее время я пытаюсь интегрировать приложение 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> не был внутренним и запечатанным. Я почти наверняка лаем на неправильное дерево здесь, но мне было бы интересно услышать, если кто-то столкнулся с этим раньше.

+0

Есть ли причина, по которой вы не хотите работать с нулевыми свойствами? Это немного похоже на то, что вы пытаетесь «сражаться» с схемой базы данных, а не принимать ее ограничения и записывать свой код соответственно. –

+0

Из интереса, почему бы вам просто не сделать свойства объекта null = false в свойствах CSDL/model. Хотя базовый SSDL имеет значение NULL, он корректно отображает непустые значения, но если значение null в БД будет изменено, вам нужно обработать исключение ConstraintException (свойство XXX в yyy не может быть установлено в свойство null) – StuartLC

+0

@ AndrewStephens Я не хочу этого делать, потому что не следует создавать базу данных. Например, существует также ситуация, когда два разных объекта хранятся в одной таблице, которые я решил с помощью Entity Framework. Я хотел бы повторно интерпретировать данные на прикладном уровне, а затем в будущем, исправить базу данных, когда это возможно. Если я допустил значения NULL в классах на уровне Entity Framework (и это было бы почти все поля, даже внешние ключи), я не решаю эту проблему. –

ответ