Получать доступ к базе данных Entity Framework с внедрением зависимостей из метода класса stati c - PullRequest
1 голос
/ 31 марта 2020

В моем проекте у меня есть метод c преобразования для преобразования объектов клиента и базы данных друг в друга. Один из этих методов stati c должен получить доступ к базе данных. До введения внедрения зависимостей в мой проект это было довольно просто:

internal async static Task<ViewerColumn> FromClientColumn(ViewerColumnSettings col) {
    using MpaContext db = new MpaContext();

    return new ViewerColumn() {
        // ...
        SourceColumnID = await db.SourceColumns
            .Where(sc => sc.Key == col.DataField)
            .Select(sc => sc.ID)
            .SingleAsync()
    };
}

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

internal async static Task<ViewerColumn> FromClientColumn(ViewerColumnSettings col, MpaContext context) {
    using MpaContext db = context;
    // ...
}

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

Вот как метод вызывается (в настоящее время с параметром context):

// Controller method with dependency injection
[HttpPut("ViewerRoles/{vrID}")]
public async Task<ActionResult> UpdateViewSettings(int vrID, ViewerRoleSettings updatedData) {
    using MpaContext db = _mpaContext;

    await storedViewerRole.ApplyViewerRoleSettingsAsync(updatedData, _mpaContext);
}

// ViewerRole.cs
internal async Task ApplyViewerRoleSettingsAsync(ViewerRoleSettings updatedData, MpaContext context) {
    // Create new entries
    foreach (Client.ViewerColumnSettings col in updatedData.ViewerColumns) {
        ViewerColumns.Add(await ViewerColumn.FromClientColumn(col, context));
    }
}

Этот подход терпит неудачу, потому что контекст располагается в UpdateViewSettings и в FromClientColumn.

Какой подход наилучшей практики для такого случая? Я мог бы распоряжаться только контекстом, если он не был открыт заранее, но для меня это звучит глупо.

1 Ответ

1 голос
/ 31 марта 2020

Инверсия зависимости / Инъекция зависимости не подходит для stati c.

Создание абстракции и производной реализации с внедренным контекстом

public class ViewerColumnService : IViewerColumnService {
    private readonly MpaContext db ;

    public ViewerColumnService  (MpaContext db) {
        this.db = db;
    }

    public async Task<ViewerColumn> FromClientColumn(ViewerColumnSettings col) {
        return new ViewerColumn() {
            // ...
            SourceColumnID = await db.SourceColumns
                .Where(sc => sc.Key == col.DataField)
                .Select(sc => sc.ID)
                .SingleAsync()
        };
    }
}

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

...