Steve Van Lint Ответов: 3

Один и тот же запрос, несколько dbcontext


Привет,

Я создал систему мониторинга для наших облачных сред.

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

Ситуация выглядит следующим образом:

У меня есть свой сайт мониторинга (ASP.NET Core + EF Core), который получает свои данные из базы данных на сервере баз данных. Эта база данных выполняет запланированные хранимые процедуры, которые захватывают различные вещи, которые я хочу контролировать, из всех баз данных на сервере.

Это работает хорошо и быстро. В моей первой версии я выполнял курсор на всех базах данных с каждым веб-запросом, так что это было не слишком эффективно.

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

Я хотел бы избежать создания нового сайта монитора для каждого нового сервера базы данных.

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

То, что я сделал до сих пор, - это создал несколько классов DbContext, указывающих на их соответствующий сервер баз данных и базу данных "ошибок", но совместно использующих одни и те же сущности.

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

Хотя это работает, должен же быть лучший способ справиться с этим?

Любое предложение будет оценено по достоинству.

Что я уже пробовал:

Я попытался поискать в интернете похожие установки, но не смог найти ни одной подходящей для моей ситуации.

3 Ответов

Рейтинг:
9

Steve Van Lint

Я нашел способ заставить это работать.

Различные БД находятся в одном домене, и у меня есть необходимые права на все из них.

Что я буду делать, так это создавать связанные серверы в качестве объектов базы данных.

Моя основная БД will we db1, и я буду использовать ее для заполнения таблиц ошибками.

Из db1 я создам связанные серверы с db2 и 3 (для целей записи).

Db2 и 3 будут иметь связанный сервер с db1 и оба будут иметь копию базы данных захвата, но без таблиц, только хранимые процедуры.

Эти SP запишут свою информацию непосредственно в db1, и там я сохраню точку происхождения ошибки (db1, db2 или db3).

Таким образом, мне нужно только запросить 1 хранилище данных, чтобы получить всю необходимую информацию.

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

Для этого я, вероятно,пойду с предложением Ричардса и создам новый экземпляр DbContext и передам параметр connection.


Рейтинг:
2

Dave Kreskowiak

Да, не используйте Entity Framework. Проблема с его использованием заключается в том, что ваш DbContext напрямую связан с точной версией базы данных, для которой был написан контекст. Если схема базы данных изменяется, то вместе с ней должен измениться и DbContext. Это предотвращает использование одного и того же DbContext для нескольких баз данных, даже если они имеют общую структурную таблицу.

Либо вам придется переключиться на использование классов Sql в .NET для каждой отдельной базы данных, либо каждое из ваших других приложений сайта придется переделать, чтобы все они направляли свою информацию об ошибках в единую базу данных, предназначенную для сбора ошибок, на которой вы можете использовать Entity Framework.


Richard Deeming

Не уверен, что соглашусь с этим.

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

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

Возможно, вам захочется отключить миграцию, если вы не используете EF для определения базы данных. Таким образом, вы не получите __MigrationHistory стол.

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

Рейтинг:
1

Richard Deeming

Если все DbContext классы разделяют одни и те же сущности, почему бы просто не создать одну DbContext класс и использовать конструктор, который принимает имя строки подключения для создания экземпляров, указывающих на разные базы данных?

public sealed class ErrorsContext : DbContext
{
    public ErrorsContext(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }
    
    public ISet<Error> Errors 
    {
        get { return Set<Error>(); }
    }
}

public sealed class ErrorsContextConfiguration : DbConfiguration
{
    public ErrorsContextConfiguration()
    {
        // Don't attempt to create / update the database:
        SetDatabaseInitializer(new NullDatabaseInitializer<ErrorsContext>());
    }
}

Затем вы можете использовать один метод для запроса любого сервера:
public static IEnumerable<Error> SingleServerQuery(this ErrorsContext context)
{
    return context.Errors. ... ;
}

а затем вызовите это для каждого экземпляра контекста и объедините результаты:
public static IEnumerable<Error> MultiServerQuery(params ErrorsContext[] servers)
{
    return servers.SelectMany(context => SingleServerQuery(context));
}


Steve Van Lint

Это действительно избавило бы от необходимости создавать новый DbContext для каждого сервера баз данных, но мне все равно пришлось бы выполнять один и тот же запрос x раз для каждого сервера баз данных.

Мне все равно нужно будет иметь возможность выполнять обновления базы данных.

В настоящее время я пробую подход со связанными серверами, где я создаю на db1 связанные серверы для db2 и db3, а затем выполняю запрос объединения с необработанным SQL.

Хотя Спасибо за предложение

Steve Van Lint

Я буду использовать этот условный подход к созданию DbContext в конце концов в сочетании со связанными серверами, см. мой последний ответ.

Спасибо за совет