Сложная функция LINQ - PullRequest
       1

Сложная функция LINQ

1 голос
/ 17 мая 2011


В моем приложении есть такие объекты, как Пользователь, Персона и Группа, которые также имеют тип IMember (поскольку они могут быть членами некоторой группы пользователей).В моей базе данных MS SQL 2008 также есть таблицы User, Person и Group, в которых хранятся соответствующие данные сущностей.
Мне часто нужно получать все эти сущности или коллекции сущностей как одну коллекцию - например, когда я получаю все члены некоторыхгруппа или я ищу участников по их именам или что-то еще.Для этого я хотел бы иметь ОДИН метод приложения, в котором определены все таблицы, соответствующие типу IMember (в будущем могут быть добавлены некоторые таблицы).Эта функция должна возвращать все извлеченные объекты в одной коллекции, и я также хочу, чтобы функция принимала некоторые условия для выполнения необходимого запроса для каждой таблицы, потому что у меня будет ряд более специфических функций, вызывающих вышеуказанное.Например, если я хочу получить все IMember, имена которых являются «ник», функция должна искать «ник» в таблицах пользователей, лиц и групп.Каков наилучший способ выполнить такие условия и сохранить оптимальный итоговый SQL-запрос?
Спасибо!

1 Ответ

0 голосов
/ 17 мая 2011

Во-первых, я хотел бы изложить вашу проблему так, как я ее понимаю. У вас есть несколько таблиц в базе данных, например:

--SQL DDL
CREATE TABLE [User](
  Name varchar(25),
  Location varchar(50)
  --Other User specific columns like login, expireDate etc.
)

CREATE TABLE Person(
  Name varchar(25),
  Location varchar(50)
  --Other Person specific columns like Birthday etc.
)

Все таблицы имеют группу столбцов base , которые представляют элемент. В коде у вас есть интерфейс IMember, определенный так. (Вы работаете в C # или VB?)

//C# code
interface IMember
{
    string Name { get; set; }
    string Location { get; set; }
}

'VB code
Interface IMember
    Property Name As String
    Property Location As String
End Interface

То, что вы хотели бы, это работать со всеми IMembers как логически единая коллекция. Было бы неплохо получить дополнительную информацию о любых ограничениях или предпочтениях, которые у вас могут быть, например: возможно ли это / у вас есть доступ для изменения макета базы данных? Можете ли вы добавить хранимые процедуры в базу данных для облегчения операций с коллекцией. Это просто выбирает пользователей, которые вам нужны, или вам нужно также иметь возможность вставлять / обновлять / удалять участников? Можно ли перекомпилировать ваш код с минимальным количеством изменений при добавлении новой производной таблицы-члена в БД. Кроме того, если вы собираетесь запрашивать решение, которое может включать фрагменты кода, было бы полезно знать, какой язык .NET вы предпочитаете, если таковой имеется. Также «оптимальный» имеет много значений для многих, самый простой с точки зрения кода? самый быстрый? наименьшее количество поездок туда и обратно? является действительно оптимальным требованием или «достаточно хорошим»?

Тем не менее, вот несколько возможных решений

Возможное решение № 1: Вы могли бы реструктурировать свои таблицы так:

--SQL DDL
CREATE TABLE Member(
  MemberID int PRIMARY KEY,
  Name varchar(25)
  Location varchar(50)
)

CREATE TABLE User(
  MemberID int FOREIGN KEY,
  --Other User specific columns like login, expireDate etc.
)

CREATE TABLE Person(
 MemberID int FOREIGN KEY,
  --Other Person specific columns like Birthday etc.
)

С новой структурой ваша проблема станет проще. Вы можете SELECT, UPDATE, DELETE (с установкой каскадного удаления) в таблице Member с помощью linq-to-sql. Любые новые таблицы, которые будут добавлены позже, будут просто следовать той же форме присоединения к таблице Member с внешним ключом, и никакие приложения не будут нуждаться в перекомпиляции. Если это невозможно, пожалуйста, объясните, почему.

Возможное решение № 2 Давайте предположим, что вышеупомянутое не возможно из-за унаследованных проблем или проблем с разрешениями. Было бы возможно установить представления или хранимые процедуры, чтобы имитировать вышеупомянутое решение. Что-то вроде следующей хранимой процедуры позволит вам выбрать всех участников по имени. Вставки / обновления / удаления могут быть более сложными, если они необходимы.

CREATE PROCEDURE GetMemberByName @Name varchar(25) AS
BEGIN
        SELECT Name, Location FROM [User]
  UNION SELECT Name, Location FROM Person
  --Add more tables here when available
  WHERE NAME = @Name
END

Опять же, это решение, при котором вы не будете перекомпилировать свой код при добавлении новой таблицы.

Возможное решение № 3 Наконец, решение в коде может быть больше, чем вы ищете. Опять же мои вопросы о специфике актуальны. Когда будет добавлена ​​новая таблица, вы собираетесь перекомпилировать свои классы L2S? Если да, вы можете просто добавить интерфейс IMember к каждому из ваших классов таблиц, а затем выставить свойство IQueryable<IMember> / IQueryable(Of IMember)) в частичном классе вашего производного контекста данных, который обеспечивает .Concat() всех задействованных таблиц. , Если нет, вам, возможно, придется запросить системные таблицы базы данных, чтобы все таблицы имели все необходимые свойства IMember в виде столбцов, и выберите их объединение. Это похоже на большую работу, и я бы не завидовал тебе, если бы тебе пришлось идти по этому пути.

Кроме того, возможное требование записывать обновления / вставки / удаления в соответствующую таблицу, возможно, придется циклически перебирать возможные таблицы, чтобы изменить правильную таблицу. Есть ли в таблицах ключ uniq w.r.t. все членские таблицы. Это отличный пример, когда GUID будет сиять, потому что, если у вас есть Пользователь с именем Джо и Персона с именем Джо, и у них один и тот же суррогатный ключ 1234, тогда, когда эта сущность находится в коллекции IMember, как бы вы узнали, что обновить / вставить / удалить?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...