Khung thực thể: Một cơ sở dữ liệu, nhiều DbContexts. Đây có phải là một ý tưởng tồi? [đóng cửa]


212

Ấn tượng của tôi cho đến nay là một DbContextý nghĩa đại diện cho cơ sở dữ liệu của bạn và do đó, nếu ứng dụng của bạn sử dụng một cơ sở dữ liệu, bạn chỉ muốn một cơ sở dữ liệu DbContext.

Tuy nhiên, một số đồng nghiệp muốn chia các khu vực chức năng thành DbContextcác lớp riêng biệt .

Tôi tin rằng điều này đến từ một nơi tốt - mong muốn giữ mã sạch hơn - nhưng nó có vẻ không ổn định. Ruột của tôi nói với tôi rằng đó là một ý tưởng tồi, nhưng thật không may, cảm giác ruột của tôi không phải là điều kiện đủ cho một quyết định thiết kế.

Vì vậy, tôi đang tìm kiếm:

A) các ví dụ cụ thể về lý do tại sao điều này có thể là một ý tưởng tồi;

B) đảm bảo rằng tất cả điều này sẽ làm việc tốt.


Xem câu trả lời của tôi: stackoverflow.com/questions/8244405/
Ấn

Câu trả lời:


168

Bạn có thể có nhiều bối cảnh cho cơ sở dữ liệu duy nhất. Ví dụ, nó có thể hữu ích nếu cơ sở dữ liệu của bạn chứa nhiều lược đồ cơ sở dữ liệu và bạn muốn xử lý từng vùng như một khu vực riêng biệt.

Vấn đề là khi bạn muốn sử dụng mã trước tiên để tạo cơ sở dữ liệu của mình - chỉ có ngữ cảnh duy nhất trong ứng dụng của bạn có thể làm điều đó. Thủ thuật cho điều này thường là một bối cảnh bổ sung có chứa tất cả các thực thể của bạn chỉ được sử dụng để tạo cơ sở dữ liệu. Bối cảnh ứng dụng thực của bạn chỉ chứa các tập hợp con của các thực thể của bạn phải có bộ khởi tạo cơ sở dữ liệu được đặt thành null.

Có một số vấn đề khác bạn sẽ thấy khi sử dụng nhiều loại ngữ cảnh - ví dụ như các loại thực thể được chia sẻ và việc chuyển từ bối cảnh này sang bối cảnh khác, v.v. Nói chung có thể, nó có thể làm cho thiết kế của bạn sạch hơn và tách biệt các khu vực chức năng khác nhau nhưng nó có chi phí phức tạp thêm.


21
Sử dụng ngữ cảnh đơn cho mỗi ứng dụng có thể tốn kém nếu ứng dụng có nhiều thực thể / bảng. Do đó, tùy thuộc vào lược đồ, nó cũng có thể có nhiều bối cảnh.
DarthVader

7
Vì tôi không đăng ký số nhiều, tôi đã tìm thấy bài viết tuyệt vời này của Julie Lerman ( bình luận của cô ) được viết tốt sau Q / A này, nhưng rất thích hợp: msdn.microsoft.com/en-us/magazine/jj883952.aspx
Dave T.

Tôi đề nghị, khung thực thể để hỗ trợ nhiều dbcontexts trong cùng một cơ sở dữ liệu bằng cách đặt tên quy ước. Vì lý do này, tôi vẫn đang viết ORM của riêng mình cho mục đích ứng dụng mô-đun. Thật khó để tin rằng nó buộc ứng dụng duy nhất sử dụng cơ sở dữ liệu duy nhất. Đặc biệt trong các trang trại web bạn có số lượng cơ sở dữ liệu giới hạn
ý chí tự do

Ngoài ra, tôi nhận ra rằng Bạn chỉ có thể Kích hoạt-Di chuyển cho một ngữ cảnh bên trong dự án thông qua Bảng điều khiển PM.
Piotr Kwiatek

9
@PiotrKwiatek Không chắc điều này có thay đổi giữa nhận xét của bạn và bây giờ không, nhưng Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory Migrations\MyContextMigrationshoạt động ngay bây giờ.
Zack

60

Tôi đã viết câu trả lời này khoảng bốn năm trước và ý kiến ​​của tôi đã không thay đổi. Nhưng kể từ đó đã có những phát triển đáng kể trên mặt trận dịch vụ vi mô. Tôi đã thêm ghi chú cụ thể cho các dịch vụ vi mô vào cuối ...

Tôi sẽ cân nhắc với ý tưởng này, với kinh nghiệm thực tế để sao lưu phiếu bầu của tôi.

Tôi đã được đưa vào một ứng dụng lớn có năm bối cảnh cho một cơ sở dữ liệu. Cuối cùng, chúng tôi đã kết thúc việc loại bỏ tất cả các bối cảnh ngoại trừ một bối cảnh - quay trở lại một bối cảnh duy nhất.

Lúc đầu, ý tưởng về nhiều bối cảnh có vẻ như là một ý tưởng tốt. Chúng tôi có thể tách quyền truy cập dữ liệu của mình vào các miền và cung cấp một số bối cảnh gọn nhẹ. Âm thanh như DDD, phải không? Điều này sẽ đơn giản hóa việc truy cập dữ liệu của chúng tôi. Một đối số khác là về hiệu suất ở chỗ chúng ta chỉ truy cập vào bối cảnh mà chúng ta cần.

Nhưng trong thực tế, khi ứng dụng của chúng tôi phát triển, nhiều bảng của chúng tôi đã chia sẻ các mối quan hệ trên các bối cảnh khác nhau của chúng tôi. Ví dụ: truy vấn bảng A trong ngữ cảnh 1 cũng yêu cầu tham gia bảng B trong ngữ cảnh 2.

Điều này để lại cho chúng tôi một vài lựa chọn nghèo nàn. Chúng ta có thể nhân đôi các bảng trong các bối cảnh khác nhau. Chúng tôi đã thử điều này. Điều này tạo ra một số vấn đề ánh xạ bao gồm ràng buộc EF yêu cầu mỗi thực thể phải có một tên duy nhất. Vì vậy, chúng tôi đã kết thúc với các thực thể có tên Person1 và Person2 trong các bối cảnh khác nhau. Người ta có thể tranh luận rằng đây là thiết kế kém về phía chúng tôi, nhưng mặc dù những nỗ lực tốt nhất của chúng tôi, đây là cách ứng dụng của chúng tôi thực sự phát triển trong thế giới thực.

Chúng tôi cũng đã thử truy vấn cả hai bối cảnh để có được dữ liệu chúng tôi cần. Ví dụ: logic kinh doanh của chúng tôi sẽ truy vấn một nửa những gì nó cần từ bối cảnh 1 và nửa còn lại từ bối cảnh 2. Điều này có một số vấn đề lớn. Thay vì thực hiện một truy vấn theo một ngữ cảnh, chúng tôi phải thực hiện nhiều truy vấn trên các bối cảnh khác nhau. Điều này có một hình phạt hiệu suất thực sự.

Cuối cùng, tin tốt là nó đã dễ dàng loại bỏ nhiều bối cảnh. Bối cảnh được dự định là một đối tượng nhẹ. Vì vậy, tôi không nghĩ hiệu suất là một đối số tốt cho nhiều bối cảnh. Trong hầu hết các trường hợp, tôi tin rằng một bối cảnh đơn giản hơn, ít phức tạp hơn và có khả năng sẽ hoạt động tốt hơn và bạn sẽ không phải thực hiện một loạt các công việc xung quanh để làm cho nó hoạt động.

Tôi nghĩ về một tình huống trong đó nhiều bối cảnh có thể hữu ích. Một bối cảnh riêng biệt có thể được sử dụng để khắc phục sự cố vật lý với cơ sở dữ liệu trong đó nó thực sự chứa nhiều hơn một miền. Lý tưởng nhất, một bối cảnh sẽ là một đối một với một miền, sẽ là một đối một với cơ sở dữ liệu. Nói cách khác, nếu một tập hợp các bảng không liên quan đến các bảng khác trong một cơ sở dữ liệu nhất định, thì có lẽ chúng nên được kéo ra một cơ sở dữ liệu riêng biệt. Tôi nhận ra điều này không phải lúc nào cũng thực tế. Nhưng nếu một tập hợp các bảng khác nhau đến mức bạn sẽ cảm thấy thoải mái khi tách chúng thành một cơ sở dữ liệu riêng biệt (nhưng bạn chọn không) thì tôi có thể thấy trường hợp sử dụng một bối cảnh riêng biệt, nhưng chỉ vì thực sự có hai miền riêng biệt.

Về dịch vụ vi mô, một bối cảnh duy nhất vẫn có ý nghĩa. Tuy nhiên, đối với các dịch vụ vi mô, mỗi dịch vụ sẽ có bối cảnh riêng chỉ bao gồm các bảng cơ sở dữ liệu có liên quan đến dịch vụ đó. Nói cách khác, nếu dịch vụ x truy cập bảng 1 và 2 và dịch vụ y truy cập bảng 3 và 4, mỗi dịch vụ sẽ có bối cảnh duy nhất của riêng nó bao gồm các bảng dành riêng cho dịch vụ đó.

Tôi quan tâm đến suy nghĩ của bạn.


8
Tôi phải đồng ý ở đây, đặc biệt khi nhắm mục tiêu một cơ sở dữ liệu hiện có. Tôi đang giải quyết vấn đề này ngay bây giờ và cảm giác ruột của tôi cho đến nay là: 1. Có cùng một bảng vật lý trong nhiều bối cảnh là một ý tưởng tồi. 2. Nếu chúng ta không thể quyết định rằng một bảng thuộc về bối cảnh này hay bối cảnh khác, thì hai bối cảnh không đủ khác biệt để được phân tách một cách hợp lý.
jkerak

3
Tôi sẽ lập luận rằng, khi thực hiện CQRS, bạn sẽ không có bất kỳ mối quan hệ nào giữa các bối cảnh (mỗi chế độ xem có thể có bối cảnh riêng) nên cảnh báo này không áp dụng cho mọi trường hợp khi một người có thể muốn có nhiều bối cảnh. Thay vì tham gia và tham chiếu, hãy sử dụng sao chép dữ liệu cho từng bối cảnh. - Điều này không phủ nhận tính hữu ích của câu trả lời này :)
urbanhusky

1
Tôi cảm thấy nỗi đau mà bạn phải đối mặt sâu sắc! : / Tôi cũng nghĩ rằng một bối cảnh là sự lựa chọn tốt hơn cho sự đơn giản.
ahmet

1
Lập luận duy nhất của tôi chống lại, lưu ý rằng tôi hoàn toàn đồng ý, liên quan đến Danh tính. Đặc biệt với tỷ lệ ngang, lớp nhận dạng cần tách ra trong hầu hết các trường hợp giới thiệu cân bằng tải. Ít nhất, đó là những gì tôi đang tìm kiếm.
Barry

5
Đối với tôi có vẻ như bạn đã không đi DDD mọi lúc, nếu các tập hợp của bạn cần biết các tập hợp khác. Nếu bạn cần tham khảo một cái gì đó, có hai lý do tại sao: chúng nằm trong cùng một tổng hợp có nghĩa là chúng phải được thay đổi trong cùng một giao dịch hoặc chúng không và bạn đã nhầm ranh giới của mình.
Simons0n

54

Chủ đề này chỉ nổi lên trên StackOverflow và vì vậy tôi muốn đưa ra một "B) đảm bảo rằng tất cả sẽ ổn" :)

Tôi đang thực hiện chính xác điều này bằng cách sử dụng mẫu Bối cảnh giới hạn DDD. Tôi đã viết về nó trong cuốn sách của mình, Khung thực thể lập trình: DbContext và nó là trọng tâm của một mô-đun 50 phút trong một trong các khóa học của tôi về Pluralsight -> http://pluralsight.com/training/Cifts/TableOfContents/efarch architecture


7
Tuy nhiên, video đào tạo đa năng rất tốt trong việc giải thích các khái niệm lớn, tuy nhiên, các ví dụ bạn đưa ra quá tầm thường so với giải pháp doanh nghiệp, (ví dụ như NuGet của các hội đồng với định nghĩa DbContext tồn tại hoặc lắp ráp mô đun.) Bối cảnh giới hạn DDD đã bị phá vỡ hoàn toàn bởi ví dụ cuối cùng của bạn trong đó một DbContext trùng lặp được xác định để giữ các khai báo trùng lặp cho mỗi Dbset. Tôi đánh giá cao rằng bạn bị giới hạn bởi công nghệ. Tôi thực sự thích video của bạn, nhưng điều này khiến tôi muốn nhiều hơn nữa.
Victor Romeo

5
Tôi đã def nhắm đến bức tranh lớn. các vấn đề về các gói nuget trong các ứng dụng lớn khá khó hiểu đối với một video ef. Ví dụ "hỏng" ... Hả? Có lẽ tốt hơn để đưa điều này đến convo riêng vì một bài phê bình về khóa học của tôi khá nằm ngoài phạm vi (và có thể không phù hợp) cho diễn đàn này. Tôi nghĩ SO cho phép bạn liên hệ trực tiếp với tôi.
Julie Lerman

57
Thật tuyệt khi được Julie chia sẻ một số thông tin về vấn đề / câu hỏi của OP. Thay vào đó, bài viết chỉ là để thúc đẩy đăng ký trả tiền cho số nhiều. Nếu một phích cắm cho một sản phẩm, ít nhất một liên kết đến thông tin về giải pháp được đề xuất (Mẫu ngữ cảnh giới hạn DDD) sẽ hữu ích. Có phải 'DDD' được mô tả trong p.222 của "Khung thực thể lập trình: DBContext" không? Bởi vì tôi đã tìm (không có chỉ mục) cho 'DDD' hoặc thậm chí là 'Bối cảnh bị ràng buộc', và không thể xác định vị trí ... Không thể chờ bạn thực hiện các sửa đổi mới cho EF6 ...
từ bi

12
xin lỗi, tôi đã không cố gắng quảng bá, chỉ thêm vào OP "muốn đảm bảo". Ladislav và những người khác đã làm một công việc tuyệt vời với các chi tiết. Vì vậy, tôi chỉ đang cố gắng để một cái gì đó tôi đã tạo ra đi sâu hơn nhiều so với tôi có thể chuyển tiếp trên SO. Dưới đây là các tài nguyên khác mà tôi đã trình bày một số nội dung độc lập : msdn.microsoft.com/en-us/magazine/jj883952.aspx & msdn.microsoft.com/en-us/magazine/dn342868.aspx & oredev.org / 2013 / wed-fri-conference /
Lỗi

tóm tắt các đề xuất mã của @JulieLerman xem câu trả lời của tôi stackoverflow.com/a/36789520/1586498
OzBob

46

Phân biệt bối cảnh bằng cách đặt lược đồ mặc định

Trong EF6, bạn có thể có nhiều ngữ cảnh, chỉ cần chỉ định tên cho lược đồ cơ sở dữ liệu mặc định trong OnModelCreatingphương thức của DbContextlớp dẫn xuất của bạn (nơi có cấu hình Fluent-API). Điều này sẽ hoạt động trong EF6:

public partial class CustomerModel : DbContext
{   
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("Customer");

        // Fluent API configuration
    }   
}

Ví dụ này sẽ sử dụng "Khách hàng" làm tiền tố cho các bảng cơ sở dữ liệu của bạn (thay vì "dbo"). Quan trọng hơn, nó cũng sẽ thêm tiền tố vào __MigrationHistorybảng, vd Customer.__MigrationHistory. Vì vậy, bạn có thể có nhiều hơn một __MigrationHistorybảng trong một cơ sở dữ liệu, một bảng cho mỗi bối cảnh. Vì vậy, những thay đổi bạn thực hiện cho một bối cảnh sẽ không gây rối với bối cảnh khác.

Khi thêm di chuyển, chỉ định tên đủ điều kiện của lớp cấu hình của bạn (xuất phát từ DbMigrationsConfiguration) làm tham số trong add-migrationlệnh:

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


Một từ ngắn trên khóa ngữ cảnh

Theo bài viết MSDN này " Chương - Nhiều mô hình nhắm mục tiêu vào cùng một cơ sở dữ liệu ", EF 6 có thể sẽ xử lý tình huống ngay cả khi chỉ có một MigrationHistorybảng tồn tại, vì trong bảng có một cột ContextKey để phân biệt các lần di chuyển.

Tuy nhiên tôi thích có nhiều hơn một MigrationHistorybảng bằng cách chỉ định lược đồ mặc định như được giải thích ở trên.


Sử dụng các thư mục di chuyển riêng

Trong trường hợp như vậy, bạn cũng có thể muốn làm việc với các thư mục "Di chuyển" khác nhau trong dự án của mình. Bạn có thể thiết lập DbMigrationsConfigurationlớp dẫn xuất của mình cho phù hợp bằng cách sử dụng thuộc MigrationsDirectorytính:

internal sealed class ConfigurationA : DbMigrationsConfiguration<ModelA>
{
    public ConfigurationA()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelA";
    }
}

internal sealed class ConfigurationB : DbMigrationsConfiguration<ModelB>
{
    public ConfigurationB()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelB";
    }
}


Tóm lược

Nói chung, bạn có thể nói rằng mọi thứ đều được phân tách rõ ràng: Bối cảnh, thư mục Di chuyển trong dự án và các bảng trong cơ sở dữ liệu.

Tôi sẽ chọn một giải pháp như vậy, nếu có các nhóm thực thể là một phần của chủ đề lớn hơn, nhưng không liên quan (thông qua khóa ngoại) với nhau.

Nếu các nhóm thực thể không có bất cứ điều gì để làm với nhau, tôi sẽ tạo một cơ sở dữ liệu riêng cho từng nhóm và cũng truy cập chúng trong các dự án khác nhau, có thể với một bối cảnh duy nhất trong mỗi dự án.


Bạn làm gì khi cần cập nhật 2 thực thể trong các bối cảnh khác nhau?
sotn

Tôi sẽ tạo một lớp (dịch vụ) mới biết cả hai bối cảnh, nghĩ về một cái tên hay và trách nhiệm của lớp này và thực hiện cập nhật này theo một trong các phương thức của nó.
Martin

7

Ví dụ đơn giản để đạt được những điều dưới đây:

    ApplicationDbContext forumDB = new ApplicationDbContext();
    MonitorDbContext monitor = new MonitorDbContext();

Chỉ phạm vi các thuộc tính trong ngữ cảnh chính: (được sử dụng để tạo và duy trì DB) Lưu ý: Chỉ sử dụng được bảo vệ: (Thực thể không được hiển thị ở đây)

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("QAForum", throwIfV1Schema: false)
    {

    }
    protected DbSet<Diagnostic> Diagnostics { get; set; }
    public DbSet<Forum> Forums { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Thread> Threads { get; set; }
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

MonitorContext: Tiếp xúc thực thể riêng biệt ở đây

public class MonitorDbContext: DbContext
{
    public MonitorDbContext()
        : base("QAForum")
    {

    }
    public DbSet<Diagnostic> Diagnostics { get; set; }
    // add more here
}

Mô hình chẩn đoán:

public class Diagnostic
{
    [Key]
    public Guid DiagnosticID { get; set; }
    public string ApplicationName { get; set; }
    public DateTime DiagnosticTime { get; set; }
    public string Data { get; set; }
}

Nếu bạn muốn, bạn có thể đánh dấu tất cả các thực thể là được bảo vệ bên trong ApplicationDbContext chính, sau đó tạo các bối cảnh bổ sung khi cần cho mỗi phân tách lược đồ.

Tất cả đều sử dụng cùng một chuỗi kết nối, tuy nhiên họ sử dụng các kết nối riêng biệt, do đó không giao dịch chéo và nhận thức được các vấn đề về khóa. Nói chung, sự tách biệt thiết kế của bạn vì vậy điều này không nên xảy ra.


2
Điều này đã giúp rất nhiều. Bối cảnh "phụ" không cần khai báo bảng chia sẻ. Chỉ cần thêm thủ công DbSet<x>định nghĩa của nó . Tôi làm điều đó trong một lớp phù hợp với những gì Nhà thiết kế EF tạo ra.
Glen Little

Bạn đã cứu tôi rất nhiều đau đầu, thưa ông! Bạn đã cung cấp một giải pháp cụ thể thay vì câu trả lời được chấp nhận. Rất cảm kích!
WoIIe

6

Nhắc nhở: Nếu bạn kết hợp nhiều bối cảnh, hãy đảm bảo bạn cắt n dán tất cả các chức năng trong nhiều bối cảnh của bạn RealContexts.OnModelCreating()vào trong một CombinedContext.OnModelCreating().

Tôi chỉ lãng phí thời gian để tìm hiểu lý do tại sao thác của tôi xóa các mối quan hệ không được bảo tồn chỉ để phát hiện ra rằng tôi đã không chuyển modelBuilder.Entity<T>()....WillCascadeOnDelete();mã từ bối cảnh thực của mình vào bối cảnh kết hợp.


6
Thay vì cắt và dán, bạn có thể gọi OtherContext.OnModelCreating()từ bối cảnh kết hợp của bạn?
AlexFoxGill 17/2/2015

4

Ruột của tôi nói với tôi điều tương tự khi tôi bắt gặp thiết kế này.

Tôi đang làm việc trên một cơ sở mã nơi có ba dbContexts cho một cơ sở dữ liệu. 2 trong số 3 dbcontexts phụ thuộc vào thông tin từ 1 dbcontext vì nó phục vụ dữ liệu quản trị. Thiết kế này đã đặt các ràng buộc về cách bạn có thể truy vấn dữ liệu của mình. Tôi gặp vấn đề này khi bạn không thể tham gia trên dbcontexts. Thay vào đó, những gì bạn bắt buộc phải làm là truy vấn hai dbcontexts riêng biệt sau đó thực hiện nối vào bộ nhớ hoặc lặp qua cả hai để có được kết hợp cả hai như một tập kết quả. Vấn đề với điều đó là thay vì truy vấn một tập kết quả cụ thể mà bạn hiện đang tải tất cả các bản ghi của mình vào bộ nhớ và sau đó thực hiện nối với hai tập kết quả trong bộ nhớ. Nó thực sự có thể làm mọi thứ chậm lại.

Tôi sẽ đặt câu hỏi "chỉ vì bạn có thể, nên bạn? "

Xem bài viết này cho vấn đề tôi gặp phải liên quan đến thiết kế này. Biểu thức LINQ được chỉ định chứa tham chiếu đến các truy vấn được liên kết với các bối cảnh khác nhau


3
Tôi đã làm việc trên một hệ thống lớn, nơi chúng tôi có nhiều bối cảnh. Một trong những điều mà tôi tìm thấy là đôi khi bạn phải đưa cùng một Dbset vào nhiều ngữ cảnh. Một mặt điều này phá vỡ một số mối quan tâm thuần túy, nhưng nó cho phép bạn hoàn thành các truy vấn của mình. Đối với trường hợp có một số bảng quản trị nhất định mà bạn cần đọc, bạn có thể thêm chúng vào lớp DbContext cơ sở và kế thừa chúng trong ngữ cảnh mô-đun ứng dụng của bạn. Mục đích bối cảnh quản trị "thực" của bạn có thể được xác định lại là "cung cấp bảo trì cho các bảng quản trị", thay vì cung cấp tất cả quyền truy cập vào chúng.
JMarsch

1
Đối với những gì nó có giá trị, tôi luôn luôn đi đi lại lại về việc liệu nó có xứng đáng hay không. Một mặt, với các bối cảnh riêng biệt, sẽ ít có thông tin hơn cho một nhà phát triển chỉ muốn làm việc trên một mô-đun và bạn cảm thấy an toàn hơn khi xác định và sử dụng các phép chiếu tùy chỉnh (vì bạn không lo lắng về các hiệu ứng mà nó sẽ gây ra mô-đun). Mặt khác, bạn gặp phải một số vấn đề khi bạn cần chia sẻ bối cảnh dữ liệu.
JMarsch

1
Bạn KHÔNG bao gồm các thực thể trong cả hai bạn luôn có thể lấy id và thực hiện truy vấn thứ 2 đến một bối cảnh khác. Đối với các hệ thống nhỏ, điều này là xấu, đối với các DB / hệ thống lớn hơn có nhiều nhà phát triển kết cấu nhiều bảng là một vấn đề lớn hơn và khó khăn hơn nhiều so với 2 truy vấn.
dùng1496062

4

Lấy cảm hứng từ [Điều khoản DDD MSDN Mag của [@JulieLerman 2013] [1]

    public class ShippingContext : BaseContext<ShippingContext>
{
  public DbSet<Shipment> Shipments { get; set; }
  public DbSet<Shipper> Shippers { get; set; }
  public DbSet<OrderShippingDetail> Order { get; set; } //Orders table
  public DbSet<ItemToBeShipped> ItemsToBeShipped { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Ignore<LineItem>();
    modelBuilder.Ignore<Order>();
    modelBuilder.Configurations.Add(new ShippingAddressMap());
  }
}

public class BaseContext<TContext>
  DbContext where TContext : DbContext
{
  static BaseContext()
  {
    Database.SetInitializer<TContext>(null);
  }
  protected BaseContext() : base("DPSalesDatabase")
  {}
}   

"Nếu bạn đang thực hiện phát triển mới và bạn muốn để Code First tạo hoặc di chuyển cơ sở dữ liệu của mình dựa trên các lớp của mình, bạn sẽ cần tạo một mô hình uber mô hình sử dụng DbContext bao gồm tất cả các lớp và mối quan hệ cần thiết xây dựng một mô hình hoàn chỉnh đại diện cho cơ sở dữ liệu. Tuy nhiên, bối cảnh này không được kế thừa từ BaseContext. " JL


2

Trong mã đầu tiên, bạn có thể có nhiều DBContext và chỉ một cơ sở dữ liệu. Bạn chỉ cần xác định chuỗi kết nối trong hàm tạo.

public class MovieDBContext : DbContext
{
    public MovieDBContext()
        : base("DefaultConnection")
    {

    }
    public DbSet<Movie> Movies { get; set; }
}

Có bạn có thể, nhưng làm thế nào bạn có thể truy vấn từ các thực thể khác nhau từ các bối cảnh db khác nhau?
Reza

2

Một chút "khôn ngoan". Tôi có một cơ sở dữ liệu đối mặt với cả hai, internet và một ứng dụng nội bộ. Tôi có một bối cảnh cho mỗi khuôn mặt. Điều đó giúp tôi giữ một sự phân biệt kỷ luật, an toàn.


1

Tôi muốn chia sẻ một trường hợp, trong đó tôi nghĩ khả năng có nhiều DBContexts trong cùng một cơ sở dữ liệu có ý nghĩa tốt.

Tôi có một giải pháp với hai cơ sở dữ liệu. Một là cho dữ liệu miền ngoại trừ thông tin người dùng. Khác chỉ dành cho thông tin người dùng. Bộ phận này chủ yếu được điều khiển bởi Quy định bảo vệ dữ liệu chung của EU . Bằng cách có hai cơ sở dữ liệu, tôi có thể tự do di chuyển dữ liệu miền (ví dụ: từ Azure sang môi trường phát triển của mình) miễn là dữ liệu người dùng ở một nơi an toàn.

Bây giờ đối với cơ sở dữ liệu người dùng, tôi đã triển khai hai lược đồ thông qua EF. Một cái là mặc định được cung cấp bởi khung Nhận dạng AspNet. Khác là của chúng tôi thực hiện bất cứ điều gì khác liên quan đến người dùng. Tôi thích giải pháp này hơn là mở rộng lược đồ ApsNet, bởi vì tôi có thể dễ dàng xử lý các thay đổi trong tương lai đối với Nhận dạng AspNet và đồng thời việc phân tách cho các lập trình viên rõ ràng rằng "thông tin người dùng của chúng ta" đi vào lược đồ người dùng cụ thể mà chúng ta đã xác định .


2
Tôi không thấy bất kỳ câu hỏi trong trả lời của tôi. Tôi không hỏi một câu hỏi duy nhất! Thay vì chia sẻ một kịch bản trong đó chủ đề của cuộc thảo luận có ý nghĩa tốt.
freilebt

0

Huh, đã dành khá nhiều thời gian cho một vấn đề với các bối cảnh DB riêng biệt cho mỗi lược đồ DB, hy vọng rằng nó sẽ giúp được ai đó ...

Gần đây tôi đã bắt đầu làm việc với một dự án có một cơ sở dữ liệu với 3 lược đồ (cách tiếp cận đầu tiên của DB), một trong số đó để quản lý người dùng. Có một bối cảnh DB được dàn dựng từ mỗi lược đồ riêng biệt. Tất nhiên, người dùng cũng liên quan đến các lược đồ khác, vd. lược đồ KB có một Chủ đề bảng, có "được tạo bởi", "được sửa đổi lần cuối bởi" vv FK thành lược đồ nhận dạng, trình ứng dụng bảng.

Các đối tượng này được tải riêng trong C #, trước tiên, chủ đề được tải từ 1 ngữ cảnh, sau đó người dùng được tải thông qua ID người dùng từ bối cảnh db khác - không hay, phải sửa lỗi này! (tương tự như sử dụng nhiều dbcontexts trong cùng một cơ sở dữ liệu với EF 6 )

Đầu tiên, tôi đã cố gắng thêm các hướng dẫn FK bị thiếu từ lược đồ nhận dạng vào lược đồ KB, vào mô hình EF trong bối cảnh KB DB. Giống như chỉ có 1 bối cảnh, nhưng tôi tách nó thành 2.

modelBuilder.Entity<Topic>(entity =>
{
  entity.HasOne(d => d.Creator)
    .WithMany(p => p.TopicCreator)
    .HasForeignKey(d => d.CreatorId)
    .HasConstraintName("fk_topic_app_users");

Nó không hoạt động, bởi vì bối cảnh kb db không có bất kỳ thông tin nào về đối tượng người dùng, lỗi trả về postgres relation "AppUsers" does not exist. Chọn câu lệnh không có thông tin thích hợp về lược đồ, tên trường, v.v.

Tôi gần như bỏ cuộc, nhưng sau đó tôi nhận thấy một công tắc "-d" khi chạy dotnet ef dbcontext scaffold. Nó viết tắt của -data-annotations - Sử dụng các thuộc tính để định cấu hình mô hình (nếu có thể). Nếu bỏ qua, chỉ API thông thạo được sử dụng. Với công tắc này được chỉ định, các thuộc tính đối tượng được xác định không phải trong ngữ cảnh db OnModelCreating(), mà là trên chính đối tượng, với các thuộc tính.

Theo cách này, EF có đủ thông tin để tạo một câu lệnh SQL thích hợp với các tên và lược đồ trường thích hợp.

TL; DR: bối cảnh DB riêng biệt không xử lý tốt các mối quan hệ (FK) giữa chúng, mỗi bối cảnh chỉ có thông tin về các thực thể riêng của nó. Khi chỉ định bật "-data-annotations" dotnet ef dbcontext scaffold, các thông tin này sẽ không được lưu trữ trong mỗi bối cảnh riêng biệt, nhưng trên chính các đối tượng DB.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.