Сделать MustOverride (абстрактный) член с EF 4? - PullRequest
0 голосов
/ 15 февраля 2011

У меня есть абстрактный класс Contact.

. Он ведет к двум подклассам:

  1. Компания (Должность)
  2. Персона (Имя, Фамилия)

Я хочу добавить вычисляемое столбец 'Title' в таблицу Person, который возвращает FirstName + '' + LastName, что даст мне лучшие параметры поиска.

Так что я хочуУ создания таблицы контактов есть абстрактное свойство Title, которое каждый из этих двух элементов реализует, и поэтому я смогу использовать:

Dim contacts = From c In context.Contacts
               Where c.Title.Contains("Nash")

Я почти уверен, что это невозможно, вопрос в том, чтоэффективный альтернативный способ?

В моем сценарии у меня есть ListBox, показывающий все Контакты обоих типов: Company и Person, у меня есть TextBox для поиска и я хочу запрос на обслуживание (GetContacts(searchQuery As String))для запроса отфильтрованного набора к базе данных.

Обновление
После ответа Уилла я решил создать в таблице Person вычисляемое col, как указано выше.Вопрос в том, что может быть наиболее эффективным способом реализации метода запроса WCF-RIA:

Public Function GetContacts(searchQuery As String) As IQueryable(Of Contact)
  'Do here whatever it takes to retieve from Contacts + People 
  'and mix the results of both tables ordered by Title
End Function

1 Ответ

2 голосов
/ 15 февраля 2011

К сожалению, хотя есть способ сделать это с частичными классами , я на 99% уверен, что вы не можете смешивать запросы linq, которые касаются свойств сущности и свойств "POCO", определенных в частичном классе.

Контекст Linq to Entity на самом деле преобразует эти запросы в sql и не может обрабатывать ситуации, когда конкретный метод напрямую не поддерживается контекстом. Типичным примером для L2E является невозможность использования перечислений в вашем запросе. Как и умение обращаться с перечислениями, контекст, конечно, не знает, как обрабатывать ваши свойства POCO при преобразовании в raw sql.

Опция, которую вы, возможно, захотите исследовать, - это создать вычисляемый столбец в вашей базе данных или выполнить ваши запросы, выполнить традиционный ToArray (), чтобы вызвать перечисление, а затем исследовать вычисляемый столбец в памяти. Однако это может быть не очень хорошим решением, в зависимости от размера вашего стола.


Таким образом, по сути, вы хотите выполнить поиск двух разнородных типов (опираясь на две разные таблицы), а затем объединить результаты для отображения пользователю.

Я бы сказал, что полиморфизм - НЕ лучшее решение. Желание показать их в пользовательском интерфейсе не должно заставлять дизайнерское решение полностью опускаться до определений вашего типа.

Я делал нечто подобное несколько раз раньше в WPF. Я сделал это двумя способами; используя полиморфизм в форме типов фасадов, которые обертывают модели и которые можно обрабатывать с помощью общего базового типа, и рассматривая все различные типы в коллекции как System.Object.

Первый способ приемлем, когда вам нужна безопасность типов и возможность одинаково обрабатывать различные типы. Оболочки расширяют общий базовый класс и кодируются, чтобы «знать», как правильно обрабатывать каждый из их обернутых типов.

Второй способ подходит, когда вам не нужна безопасность типов, например, когда вы открываете коллекцию в WPF View, где вы отображаете их в ItemsControl, который может определить правильный DataTemplate для использования по типу каждого экземпляр в коллекции.

Я не уверен, какой способ лучше для вас, но в зависимости от того, что вам нужно, вы должны запросить таблицы и компании и человека отдельно, Объединение двух наборов результатов, а затем отсортировать их соответствующим образом.

псевдокод:

//Wrapper version
var results  = Company
               .Where(x=>x.Title.Contains(searchTerm))
               .Select(x=> new CompanyWrapper(x))
               Cast<BaseWrapper>().Union(
                  Person
                      .Where(x=>x.ComputedTitle.Contains(searchTerm))
                      .Select(x=> new PersonWrapper(x))
                      .Cast<BaseWrapper>());

//System.Object version
var results  = Company
               .Where(x=>x.Title.Contains(searchTerm))
               Cast<object>().Union(
                  Person
                      .Where(x=>x.ComputedTitle.Contains(searchTerm))
                      .Cast<object>());

В обоих случаях вам может не нужно специально понижать рейтинг. Опять же, первое дает вам безопасность типов, если вам это нужно в пользовательском интерфейсе, второе проще и требует меньше кода на бэкэнде, но полезно только в том случае, если вам не требуется безопасность типов в пользовательском интерфейсе.

Что касается сортировки, после поиска и объединения результатов вы можете OrderBy отсортировать результат, однако вам нужно будет предоставить функцию, которая может выполнять упорядочивание. Эта функция зависит от выбранной версии.

...