linq2 sql C#: Как сделать запрос из таблицы с изменением имени схемы - PullRequest
0 голосов
/ 19 февраля 2020

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

У него есть таблицы с тем же именем, но с разными именами схем, например:

[DatabaseName].[202001].[CustomerCredit]
[DatabaseName].[202002].[CustomerCredit]
.
.
.
[DatabaseName].[202014].[CustomerCredit]
[DatabaseName].[202015].[CustomerCredit]
[DatabaseName].[202016].[CustomerCredit]
...
..
[DatabaseName].[2020xx].[CustomerCredit]

Схема имя имеет формат [Year+IncrementalNumber], например [202014], [202015], [202016] и т. д. c.

Всякий раз, когда я хочу запросить информацию о кредитоспособности клиента в базе данных, я должен получать информацию из схемы с помощью наибольшее число, например [DatabaseName].[202016].[CustomerCredit], если 202016 - последняя схема в моей базе данных.

Примечание: Создание новой схемы в базе данных приложения учета не имеет правил и полностью определяется пользователем приложения учета и каждый экземпляр приложения, установленного в другом месте, может иметь разное количество схем.

Поэтому, когда я разрабатываю свой веб-сервис, я не имею представления, к какой схеме подключиться до разработки. Во время выполнения я могу найти правильную схему для запроса из ее таблиц, но я не знаю, как управлять выборкой информации таблицы с правильным именем схемы в запросе. Я обычно создаю класс linq-to- sql dbml и использую его определения для чтения информации из базы данных, но я не знаю, как управлять изменением схемы таким образом?

Дизайнер DBML управляет именами Scehma, как это :

[global::System.Data.Linq.Mapping.TableAttribute(Name="[202001].CustomerCredit")]

Однако, поскольку мое приложение может получать имя схемы во время выполнения, я не знаю, как исправить объявление таблицы в моем особом случае. В ADO так легко работать. NET, но я не знаю его эквивалента в Linq2 SQL:

select count(*)  from [" + Variables.FinancialYearSchemaName + "].CustomerCredit  where SFC_Status = 100;

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Эта схема по сути является ручным разделением таблицы CustomerCredit. Лучшим решением было бы то, которое делает разделение прозрачным для всех пользователей. Код не должен знать, как данные разделены.

Решения для баз данных

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

Разделение таблицы

Чистым решением было бы использование разбиение таблицы , делая различные разделы прозрачными для всех пользователи. Раньше разделение таблиц использовалось только для Enterprise, но оно стало доступно во всех выпусках, начиная с SQL Server 2016 SP1, даже Express. Это означает, что это бесплатно во всех версиях, которые все еще поддерживаются.

Таблица разделена на основе функции (например, функции на основе даты) и хранится в разных файлах. Когда это возможно, оптимизатор запросов может проверять границы раздела и условия запроса и использовать только файл, содержащий соответствующие данные. Например, в таблице с разделением по дате запросы, содержащие фильтр даты, могут выполнять поиск только по соответствующим разделам.

Секционированные представления

Другой вариант: по крайней мере, начиная с 2000 года, это использование представлений секционирования , по сути, представления UNION ALL, объединяющего все разделы таблицы, например:

SELECT <select_list1>  
FROM [202001].[CustomerCredit]
UNION ALL  
SELECT <select_list2>  
FROM [202002].[CustomerCredit]
UNION ALL  
...  
SELECT <select_listn>  
FROM Tn;

EF может отображать сущности в представления вместо таблиц , Если критерии для обновляемых представлений соблюдены, само разделенное представление будет обновляемым и любые изменения будут внесены в правильную таблицу.

Оптимизатор запросов может использовать ограничения CHECK для таблиц для поиска только в одной таблице. в то же время, как работает секционированные таблицы.

Решения для кода

Для этого требуются необработанные SQL запросы и способ определения правильной таблицы / схемы при каждом изменении. Это требует изменений в приложении каждый раз, когда изменяется разбиение таблицы, будь то модификации кода или изменения в файле конфигурации.

Во всех случаях один запрос может считывать только одну таблицу за раз

Сохранить ADO. NET

Одна из возможностей - продолжать использовать ADO. NET, заменяя имя таблицы / схемы в шаблоне запроса. При необходимости код должен отображаться на объекты, так же, как он это уже делал.

EF Raw SQL

Другой вариант: использовать функции SQL EF, например EF Core FromSqlRaw , для запроса из определенной таблицы c, аналогично ADO. NET. Преимущество заключается в том, что EF отобразит результаты запроса на объекты. В EF Core необработанный запрос можно комбинировать с операторами LINQ:

var query=$"select * from [DatabaseName].[{schemaName}].[CustomerCredit]"
var credits = context.CustomerCredits
    .FromSqlRaw(query)
    .Where(...)
    .ToList();

Dapper

Другой вариант - использовать Dapper или другой micro-ORM с запросом ad-ho c, аналогичным ADO. NET, и сопоставляет результаты с объектами:

var query=$"select * from [DatabaseName].[{schemaName}].[CustomerCredit] where customerID=@ID";
var credits=connection.Query<CustomerCredit>(query,new {ID=someID});
1 голос
/ 19 февраля 2020

В конечном счете, нет: большинство ORM не ожидают, что изменение схемы будет изменяться во время выполнения, поэтому большинство - включая EF и LINQ-to- SQL не поддерживают этот сценарий. Один возможный вариант - иметь разные строки подключения, каждая с разными учетными записями пользователей , каждая из которых имеет свою схему по умолчанию, настроенную в базе данных, и инициализировать ваш контекст DB с помощью соединения. -строка или соединение, которое соответствует требуемой учетной записи. Затем, если EF запрашивает у СУБД [CustomerCredit], она сначала будет выглядеть в схеме этой учетной записи ([202014].[CustomerCredit]). Вам, вероятно, следует избегать с [202014].[CustomerCredit] в этом сценарии, чтобы избежать путаницы. Это, однако, довольно хакерское и уродливое решение. Но ... это должно работать.

В качестве альтернативы вам придется взять под больший контроль над доступом к данным, по сути, написать свой собственный SQL (предположительно с заменой токена для схемы, которая имеет проблемы с ее собственный).

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