Ошибка множественных подключений Entity Framework - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть сценарий, в котором у меня есть несколько строк подключения, определенных в appsettings.json, например:

"ConnectionString": {
    "ConnectionZone1": "Server=(localdb)\\mssqllocaldb;Database=Blogging;Trusted_Connection=True;",
    "ConnectionZone2": "Server=localhost;Database=Blogging;Trusted_Connection=True;"
},

Это я также зарегистрировал в своем файле startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DbContextZone1>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone1")));

        services.AddDbContext<DbContextZone2>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("ConnectionZone2")));

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

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

public partial class BloggingContext : DbContext
{
    public BloggingContext()
    {
    }

    public BloggingContext(DbContextOptions<BloggingContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Blog> Blog { get; set; }
    public virtual DbSet<Post> Post { get; set; }

и создал два других класса контекста, которые наследуются от вышеуказанного основного базового класса:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1()
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2()
    {

    }
}

Теперь я создал свои контроллеры API и пытаюсь вызвать эти методы контекста.

[HttpGet]
    public async Task<ActionResult<IEnumerable<object>>> GetItems()
    {
        if (alternate)
        {
            alternate = false;
            using (var context = new DbContextZone1())
            {
                return await context.Blog.ToListAsync();
            }
        }

        using(var context = new DbContextZone2())
        {
            return await context.Post.ToListAsync();
        }            
    }

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

enter image description here

Так что в конструкторе DbContextZone1 и DbContextZone2 какой параметр параметров контекста придет ?.Я попытался поставить как это, но он никогда не работает и выдает ошибку, когда я вызываю контроллер API:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<BloggingContext> options)
        : base(options)
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<BloggingContext> options)
        : base(options)
    {

    }
}

И это ошибка: enter image description here

ТакЛюбая помощь или идеи кода или предложения о том, как установить несколько соединений или сделать мой код правильным?.

Ответы [ 2 ]

2 голосов
/ 19 сентября 2019

Измените ваши конструкторы DbContext следующим образом:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    {
    }        
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    {

    }
}

Обновление:

Если у вас есть ошибки после изменения класса DbContext, потому что вы пытаетесьчтобы получить доступ к конструкторам по умолчанию, как показано ниже:

using (var context = new DbContextZone1())

, когда в ваших классах нет реализованного конструктора по умолчанию.Поскольку вы зарегистрировали свои классы DbContext в базовой системе DI .net, вам просто нужно внедрить DbContextZone1 и DbContextZone2 в конструктор контроллера, а затем вы можете легко получить доступ к контекстам.Но перед этим вы должны добавить свой DbSet в классы DbContext и изменить их на:

public class DbContextZone1 : BloggingContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    { }

    public virtual DbSet<Blog> Blogs { get; set;}
}

public class DbContextZone2 : BloggingContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    { }

    public virtual DbSet<Post> Posts { get; set;}
}

Примечание: вы можете сохранить ваши DbSet в BloggingContext и затем получить к ним доступ через _context в вашем контроллере, но перемещая их какВышеизложенное делает ваши контексты изолированными и дает единственную ответственность за контексты.

Теперь ваш контроллер должен выглядеть следующим образом:

private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
public MyController(DbContextZone1 context1, DbContextZone2 context2)
{
    _context1 = context1;
    _context2 = context2;
}

[HttpGet]
public async Task<ActionResult<IEnumerable<object>>> GetItems()
{
    if (alternate)
    {
        alternate = false;
        return await _context1.Blogs.ToListAsync();
    }
    return await _context2.Posts.ToListAsync();
}
1 голос
/ 20 сентября 2019

Из вашего appsettings.json кажется, что вы хотите подключиться к одной и той же базе данных на другом сервере. Вам не нужно создавать базовый DbContext, просто наследуется DbContext по умолчанию, как показано ниже:

public class DbContextZone1 : DbContext
{
    public DbContextZone1(DbContextOptions<DbContextZone1> options)
        : base(options)
    {
    }
    public virtual DbSet<Blog> Blog { get; set; }
}
public class DbContextZone2 :DbContext
{
    public DbContextZone2(DbContextOptions<DbContextZone2> options)
        : base(options)
    {
    }
    public virtual DbSet<Post> Post { get; set; }
}

И вызовите API-контроллер, как показано ниже:

private readonly DbContextZone1 _context1;
private readonly DbContextZone2 _context2;
    public ABCController(DbContextZone1 context1, DbContextZone2 context2)
    {
        _context1 = context1;
        _context2 = context2;
    }
    [HttpGet]
    public async Task<ActionResult<IEnumerable<object>>> GetItems()
    {
        //....
        if (alternate)
        {
            alternate = false;
            return await _context1.Blog.ToListAsync();
        }
        return await _context2.Post.ToListAsync();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...