11

Tôi nhận được lỗi này khi tôi cố gắng sử dụng mã di cư đầu tiên.Bắt 'Bối cảnh không phải là cấu trúc. Thêm một constructor mặc định hoặc cung cấp một thực hiện IDbContextFactory."

bối cảnh của tôi có một nhà xây dựng với tên kết nối.

public class VeraContext : DbContext, IDbContext 
{ 
    public VeraContext(string NameOrConnectionStringName = "VeraDB") 
     : base(NameOrConnectionStringName) 
    { 
    } 

    public IDbSet<User> Users { get; set; } 
    public IDbSet<Product> Products { get; set; } 
    public IDbSet<IntCat> IntCats { get; set; } 
} 

này tên kết nối được tiêm với Ninject khi dự án chạy, tôi cũng đã xác định nó như là một mặc định như trong đoạn code trên nhưng điều này đã không giúp đỡ.

kernel.Bind<IDbContext>() 
    .To<VeraContext>() 
    .WithConstructorArgument("NameOrConnectionStringName", "VeraDB"); 

khi tôi cố gắng thêm di cư với "Enable-Mi grations" là ném lên các lỗi:

The target context 'VeraData.EF.Infrastructure.VeraContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory.

Nếu tôi loại bỏ các nhà xây dựng từ VeraContext nó sẽ làm việc nhưng tạo ra một cơ sở dữ liệu với VeraData.EF.Infrastructure.VeraContext như tên của nó.

Tôi giả định rằng ninject chỉ chuyển chuỗi kết nối khi dự án chạy và không khi tôi sử dụng mã di chuyển đầu tiên. Dù sao tôi có thể tiêm/cung cấp một mặc định cho tên kết nối khi sử dụng mã di cư đầu tiên?

+1

Tất cả công cụ thứ chín xảy ra khi ai đó ở đâu đó đang thực hiện 'Kernel.Get'.Bạn cần phải thêm một ctor mặc định hoặc chờ ai đó nói cho bạn biết cách móc công cụ di chuyển để xây dựng các đối tượng thông qua Ninject (mà tôi đoán là những gì bạn đang làm!). –

+0

Bạn sẽ phải triển khai 'IDbContextFactory' để các kết quả nhất quán (hoặc việc di chuyển từ mã của bạn sẽ không hoạt động, v.v.). Về cơ bản bạn cần một ctor mặc định (đó là lỗi) - nhưng chỉ thực hiện nó sẽ dẫn đến các vấn đề. – NSGaga

+0

'IDbContextFactory' không tốt cho việc tiêm, nó sẽ không hoạt động theo thiết kế. Không thể nhìn thấy điểm của nó ... – nicodemus13

Trả lời

16

Về cơ bản bạn cần một ctor mặc định (đó là lỗi) - nhưng chỉ việc triển khai nó sẽ dẫn đến các sự cố.

Bạn sẽ phải triển khai IDbContextFactory để các kết quả nhất quán (hoặc việc di chuyển từ mã của bạn sẽ không hoạt động, v.v.).

Migrations actually call your default constructor to make a connection. So you're other ctor won't matter much.

Đây là nhà máy sản xuất cơ bản ...

public class MyContextFactory : IDbContextFactory<MyContext> 
{ 
    public MyContext Create() 
    { 
     return new MyDBContext("YourConnectionName"); 
    } 
} 

Bạn nên kết hợp điều đó với tiêm, tiêm và xây dựng DbContext của bạn như bạn muốn.

+0

Bạn có thể giải thích ý của bạn hơn nữa, bạn không thể tiêm, vì 'Tạo()' không nhận tham số và phải có một hàm tạo mặc định, luôn luôn cái gọi là - do đó, không nơi nào để tiêm. Ít nhất, không có constructor-injection. – nicodemus13

+0

@ nicodemus13 nó đã được một thời gian dài trước đây, nhưng như tôi nhớ - đó là để đảm bảo xây dựng DbContext phù hợp. đôi khi EF gọi ctor mặc định bằng cách tự động hóa, cho dù bạn muốn hay không, vì vậy bạn cần phải có một, và ctor tùy chỉnh không được gọi. Nhà máy là chủ yếu cho các cuộc gọi EF, bạn có thể sử dụng tiêm trên DbContext bình thường. Nhưng b) theo như tôi nhớ lại hầu hết các container IoC (tôi không sử dụng nhiều ninject) có cách xác định ví dụ container.Create và sau đó là một số phương pháp ẩn danh để tham gia vào nhà máy (nếu nhà máy phức tạp hơn, do đó bạn cần phải trải qua nó, nếu không như tôi đã nói) – NSGaga

+1

@NSGaga - Bất kỳ lý do nào chúng tôi không thể tiêm DbContext hoặc chuỗi kết nối vào MyContextFactory thông qua hàm tạo và sau đó trả về DbContext thay vì new'ing lên một DbContext mới trong phương thức create? –

1

để bổ sung @ nccsbim071 câu trả lời, tôi có thêm điều thêm một ... tùy chọn này không thích xây dựng với các thông số mặc định ... ví dụ:

public MyContext(bool paramABC = false) : base("name=Entities") {...} 

thay vào đó bạn phải tạo một hàm tạo không tham số (mặc định) và hàm tạo-tham số như kiểu thời trang cũ.

public MyContext() :base("name=Entities") {...} 
public MyContext(bool paramABC) : this() {...} 

LƯU Ý:

  • Entities trong trường hợp này có nghĩa là tên chuỗi kết nối ... Theo quy ước, tên của bối cảnh là giống như tên chuỗi kết nối và từ MyContext là không giống nhau là Entities, cần phải chỉ định thủ công.
Các vấn đề liên quan