Varlık Çerçevesi: Bir Veritabanı, Çoklu DbContexts. Bu kötü bir fikir mi? [kapalı]


213

Bugüne kadarki izlenimim DbContext, a'nın veritabanınızı temsil etmesi anlamına geldiğinden, uygulamanız tek bir veritabanı kullanıyorsa, yalnızca bir tane istersiniz DbContext.

Ancak, bazı meslektaşlar fonksiyonel alanları ayrı DbContextsınıflara ayırmak istiyor .

Bunun iyi bir yerden geldiğine inanıyorum - kodu daha temiz tutma arzusu - ama geçici görünüyor. Bağırsaklarım bana bunun kötü bir fikir olduğunu söylüyor ama maalesef bağırsak hissim bir tasarım kararı için yeterli bir koşul değil.

Bu yüzden arıyorum:

A) bunun neden kötü bir fikir olabileceğine dair somut örnekler;

B) bunların iyi sonuç vereceğine dair güvence verir.


Yanıtlar:


168

Tek bir veritabanı için birden fazla bağlamınız olabilir. Örneğin, veritabanınız birden çok veritabanı şeması içeriyorsa ve bunların her birini ayrı bir bağımsız alan olarak işlemek istiyorsanız yararlı olabilir.

Sorun, veritabanınızı oluşturmak için önce kodu kullanmak istediğinizde - uygulamanızdaki yalnızca tek bir bağlamda bunu yapabilir. Bunun hilesi genellikle yalnızca veritabanı oluşturmak için kullanılan tüm varlıklarınızı içeren ek bir bağlamdır. Yalnızca varlıklarınızın alt kümelerini içeren gerçek uygulama bağlamlarınızda veritabanı başlatıcısı null olarak ayarlanmış olmalıdır.

Birden çok bağlam türü kullanırken göreceğiniz başka sorunlar da vardır - örneğin paylaşılan varlık türleri ve bunların bir bağlamdan diğerine geçişi, vb. ek karmaşıklıkta maliyetler.


21
Uygulamada birden fazla varlık / tablo varsa, uygulama başına tek bir bağlam kullanmak pahalı olabilir. Dolayısıyla şemaya bağlı olarak, birden çok bağlamın olması da mantıklı olabilir.
DarthVader

7
Çoğul görüşe abone olmadığım için, Julie Qerman'ın ( yorumu ) bu Q / A'dan sonra iyi yazılmış bu harika makaleyi buldum , ancak çok uygun: msdn.microsoft.com/en-us/magazine/jj883952.aspx
Dave T.

Ben, kural isimlendirme ile aynı veritabanında birden fazla dbcontexts desteklemek için varlık çerçeve öneririm. Bu nedenle modüler uygulama amacıyla hala kendi ORM'mi yazıyorum. İnanması zor olan tek uygulamayı tek bir veritabanı kullanmaya zorlar. Özellikle web çiftliklerinde sınırlı sayıda veritabanınız var
freewill

Buna ek olarak, PM Console aracılığıyla proje içinde yalnızca bir bağlam için Taşıma İşlemlerini Etkinleştirebileceğinizi anladım.
Piotr Kwiatek

9
@PiotrKwiatek Bunun yorumunuzla şimdi arasında değiştiğinden emin değilsiniz, ancak Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory Migrations\MyContextMigrationsşimdi çalışıyor.
Zack

60

Bu cevabı yaklaşık dört yıl önce yazdım ve fikrim değişmedi. Ancak o zamandan beri mikro hizmetler cephesinde önemli gelişmeler oldu. Sonunda mikro hizmetlere özel notlar ekledim ...

Oyumu destekleyecek gerçek dünya deneyimi ile bu fikre karşı çıkacağım.

Tek bir veritabanı için beş bağlamı olan büyük bir uygulamaya getirildim. Sonunda, tek bir bağlama geri dönmek dışında, tüm bağlamları kaldırdık.

İlk başta çoklu bağlam fikri iyi bir fikir gibi görünüyor. Veri erişimimizi etki alanlarına ayırabilir ve birkaç temiz, hafif bağlam sağlayabiliriz. DDD gibi geliyor değil mi? Bu veri erişimimizi basitleştirecektir. Başka bir argüman performans için sadece ihtiyacımız olan içeriğe erişmemiz.

Ancak uygulamada, uygulamamız büyüdükçe, tablolarımızın birçoğu çeşitli bağlamlarımızda ilişkileri paylaştı. Örneğin, bağlam 1'deki tablo A'ya yönelik sorgular, bağlam 2'deki tablo B'ye katılmayı da gerektirdi.

Bu bize birkaç kötü seçenek bıraktı. Tabloları çeşitli bağlamlarda çoğaltabiliriz. Bunu denedik. Bu, her varlığın benzersiz bir ada sahip olmasını gerektiren bir EF kısıtlaması da dahil olmak üzere çeşitli haritalama sorunları yarattı. Böylece farklı bağlamlarda Person1 ve Person2 adlı varlıklarla karşılaştık. Bunun bizim için zayıf tasarım olduğunu iddia edebiliriz, ancak en iyi çabalarımıza rağmen, uygulamamız gerçek dünyada bu şekilde büyüdü.

Ayrıca ihtiyacımız olan verileri elde etmek için her iki bağlamı da sorgulamayı denedik. Örneğin, iş mantığımız bağlam 1'den ihtiyaç duyulan şeyin yarısını ve bağlam 2'den yarısını sorgulayacaktır. Bunun bazı önemli sorunları vardı. Tek bir bağlamda tek bir sorgu yapmak yerine, farklı bağlamlarda birden fazla sorgu yapmak zorunda kaldık. Bunun gerçek bir performans cezası var.

Sonunda, iyi haber şu ki, çoklu bağlamları çıkarmanın kolay olduğu. Bağlamın hafif bir nesne olması amaçlanmıştır. Bu yüzden performansın birden fazla bağlam için iyi bir argüman olduğunu düşünmüyorum. Hemen hemen her durumda, tek bir bağlamın daha basit, daha az karmaşık ve muhtemelen daha iyi performans göstereceğine inanıyorum ve işe yaraması için bir sürü çözüm uygulamak zorunda kalmayacaksınız.

Birden fazla bağlamın faydalı olabileceği bir durum düşündüm. Aslında birden fazla etki alanı içerdiği veritabanıyla ilgili fiziksel bir sorunu gidermek için ayrı bir bağlam kullanılabilir. İdeal olarak, bir bağlam bire bir etki alanına, bu da bire bir veritabanına olur. Başka bir deyişle, bir tablo kümesi belirli bir veritabanındaki diğer tablolarla hiçbir şekilde ilgili değilse, muhtemelen ayrı bir veritabanına çekilmelidir. Bunun her zaman pratik olmadığını anlıyorum. Ancak bir dizi tablo onları ayrı bir veritabanına ayırmaktan rahat hissederseniz (ancak seçmemeyi tercih ederseniz), ayrı bir bağlam kullanmak için davayı görebiliyordum, ancak sadece iki ayrı etki alanı olduğu için görebiliyordum.

Mikro hizmetler ile ilgili olarak, tek bir bağlam hala mantıklıdır. Ancak, mikro hizmetler için, her hizmetin yalnızca o hizmetle ilgili veritabanı tablolarını içeren kendi bağlamı olacaktır. Diğer bir deyişle, hizmet x tablo 1 ve 2'ye ve hizmet y tablo 3 ve 4'e erişirse, her hizmetin o hizmete özgü tabloları içeren kendine özgü bir bağlamı olur.

Düşüncelerinle ilgileniyorum.


8
Burada, özellikle var olan bir veritabanını hedeflerken katılıyorum. Şu anda bu sorun üzerinde çalışıyorum ve şimdiye kadarki bağırsak duygularım: 1. Birden fazla bağlamda aynı fiziksel tabloya sahip olmak kötü bir fikirdir. 2. Bir tablonun bir bağlamda veya başka bir bağlamda olduğuna karar veremezsek, iki bağlam mantıksal olarak ayrılacak kadar belirgin değildir.
jkerak

3
CQRS yaparken, bağlamlar arasında (her görünümün kendi bağlamı olabilir) herhangi bir ilişkiniz olmayacağını, bu uyarının birden fazla bağlamın olmasını isteyebileceği her durum için geçerli olmadığını iddia ediyorum. Birleştirme ve referans verme yerine, her bağlam için veri çoğaltma kullanın. - Bu, bu cevabın yararlılığını
olumsuz etkilemez

1
Derinlerde karşılaştığınız acıyı hissettim! : / Ben de bir bağlam basitlik için daha iyi bir seçim olduğunu düşünüyorum.
ahmet

1
Başka türlü tamamen kabul ettiğimi belirten tek argümanım Kimlik ile ilgili. Özellikle yatay ölçeklendirme ile, yük dengelemesinin getirildiği hemen hemen tüm durumlarda kimlik katmanı ayrılması gerekir. En azından, bulduğum şey bu.
Barry

5
Bana göre, agregalarınızın diğer agregaları tanıması gerekiyorsa, DDD'yi hiç gitmediniz gibi görünüyor. Bir şeye başvurmanız gerekiyorsa bunun iki nedeni vardır: aynı toplu işlemde oldukları anlamına gelir, aynı işlemde değiştirilmeleri gerekir ya da değildirler ve sınırlarınızı yanlış anladınız.
Simons0n

54

Bu iplik sadece StackOverflow üzerinde fokurdadı ve bu yüzden tüm bu iyi olacak başka bir "B) güvencesi sunmak istedim :)

Tam olarak bunu DDD Sınırlı Bağlam kalıbı ile yapıyorum. Bu konuda kitabımda yazdım, Programlama Varlığı Çerçevesi: DbContext ve bu, Çoğul Görüş'teki derslerimden birinde 50 dakikalık bir modülün odağı -> http://pluralsight.com/training/Courses/TableOfContents/efarchitecture


7
Birden fazla görüş eğitim videosu büyük kavramları açıklamakta çok iyiydi, ancak imho, verdiğiniz örnekler kurumsal bir çözüme kıyasla çok önemsizdir (örneğin, DbContext tanımlarına sahip montajlar NuGet veya dinamik olarak yüklenen modüler montajlar). DDD Sınırlı Bağlam, her bir DbSet için yinelenen bildirimler tutmak üzere yinelenen bir DbContext tanımlandığı son örneğiniz tarafından tamamen kırılmıştır. Teknolojiyle sınırlı olduğunuzu takdir ediyorum. Videolarınızı gerçekten çok beğendim, ama bu beni daha fazla istememe bıraktı.
Victor Romeo

5
Def büyük resim hedefliyordum. sorunları büyük uygulamalar yeniden nuget paketleri bir ef video için oldukça bağlam dışı. Yeniden "kırık" örnekler ... Ha? Kursumun bir eleştirisi bu forum için oldukça kapsam dışı (ve muhtemelen uygunsuz) olduğundan, bunu özel konvoya götürmek daha iyi olabilir. Sanırım SO doğrudan benimle iletişime geçmeni sağlıyor.
Julie Lerman

57
Julie OP sorun / soru hakkında bazı bilgileri paylaşmak için güzel olurdu. Bunun yerine, gönderi sadece çoğul görüşe bir ödeme aboneliğini teşvik etmektir. Bir ürün için bir eklenti varsa, önerilen çözüm (DDD Sınırlı bağlam Paterni) hakkında en azından bir bilgi bağlantısı yardımcı olacaktır. 'DDD', "Programlama Varlık Çerçevesi: DBContext", p.222'de açıklanan nedir? Çünkü 'DDD', hatta 'Sınırlı Bağlam' için (indeks yok) baktım ve bulamıyorum ... EF6 için yeni revizyonlar yapmayı bekleyemem ...
Şefkatli Narsist

12
üzgünüm, ben sadece OP "güvence istiyorum" ekleyerek, teşvik etmeye çalışmıyordu. Ladislav ve diğerleri detaylarla harika bir iş çıkardılar. Bu yüzden, daha önce oluşturduğum ve SO'ya geçiş yapabileceğimden çok daha derinlere giden bir şeyi deniyordum. İşte bazı şeyleri ayrıntılarıyla ele aldığım diğer kaynaklar: msdn.microsoft.com/en-us/magazine/jj883952.aspx & msdn.microsoft.com/en-us/magazine/dn342868.aspx & oredev.org / 2013 / wed-fri-konferans /…
Julie Lerman

@JulieLerman 'in kod önerilerinin özeti cevabımı gör stackoverflow.com/a/36789520/1586498
OzBob

46

Varsayılan şemayı ayarlayarak bağlamları ayırt etme

EF6'da birden fazla bağlamınız olabilir, türetilmiş sınıf OnModelCreatingyönteminizde DbContext(Fluent-API yapılandırmasının olduğu yerde) varsayılan veritabanı şemasının adını belirtmeniz yeterlidir . Bu EF6'da çalışacaktır:

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

        // Fluent API configuration
    }   
}

Bu örnekte, veritabanı tablolarınız için ("dbo" yerine) "Müşteri" öneki kullanılır. Daha da önemlisi, __MigrationHistorytablo (lar) ın önüne ön ek ekleyecektir Customer.__MigrationHistory. Böylece __MigrationHistory, tek bir veritabanında her bağlam için bir tane olmak üzere birden fazla tablonuz olabilir . Dolayısıyla, bir bağlam için yaptığınız değişiklikler diğer içerikle uğraşmayacaktır.

Taşıma işlemini eklerken, yapılandırma sınıfınızın (türetilmiş DbMigrationsConfiguration) tam adını add-migrationkomutta parametre olarak belirtin :

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


Bağlam anahtarında kısa bir kelime

" Bölüm - Aynı Veritabanını Hedefleyen Birden Çok Model " adlı MSDN makalesine göre EF 6, yalnızca bir MigrationHistorytablo olsa bile durumu işleyecektir , çünkü tabloda bir ContextKey vardır. geçişleri ayırt etmek için sütunu .

Ancak MigrationHistoryyukarıda açıklandığı gibi varsayılan şemayı belirterek birden fazla tabloya sahip olmayı tercih ederim .


Ayrı taşıma klasörleri kullanma

Böyle bir senaryoda, projenizdeki farklı "Taşıma" klasörleriyle de çalışmak isteyebilirsiniz. DbMigrationsConfigurationTüretilmiş sınıfınızı, MigrationsDirectoryözelliği kullanarak uygun şekilde ayarlayabilirsiniz :

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";
    }
}


özet

Sonuç olarak, her şeyin temiz bir şekilde ayrıldığını söyleyebilirsiniz: Bağlamlar, Projedeki geçiş klasörleri ve veritabanındaki tablolar.

Daha büyük bir konunun parçası olan, ancak (yabancı anahtarlarla) birbiriyle ilişkili olmayan varlık grupları varsa, böyle bir çözüm seçerdim.

Varlık gruplarının birbirleri ile ilgili yapacak bir şeyleri yoksa, her biri için ayrı bir veritabanı oluşturacak ve onlara farklı projelerde, muhtemelen her projede tek bir bağlamla erişecektim.


Farklı bağlamlarda 2 varlığı güncellemeniz gerektiğinde ne yaparsınız?
sotn

Her iki bağlamı da bilen, iyi bir isim ve bu sınıfın sorumluluklarını düşünen ve bu güncellemeyi yöntemlerinden birinde yapan yeni (hizmet) bir sınıf yaratacağım.
Martin

7

Aşağıdakilere ulaşmak için basit bir örnek:

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

Sadece özellikleri ana bağlamda kapsamlandırın: (DB oluşturmak ve korumak için kullanılır) Not: Sadece korumalı kullanın: (Varlık burada gösterilmez)

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: Ayrı Varlığı burada göster

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

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

Teşhis Modeli:

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

İsterseniz tüm varlıkları ana ApplicationDbContext içinde korumalı olarak işaretleyebilirsiniz, ardından şemaların her bir ayrılması için gereken ek bağlamları oluşturun.

Hepsi aynı bağlantı dizesini kullanır, ancak ayrı bağlantılar kullanırlar, bu yüzden işlemleri çaprazlamayın ve kilitleme sorunlarının farkında olun. Genellikle ayrımı tasarlayın, böylece bu zaten olmamalı.


2
Bu çok yardımcı oldu. "İkincil" bağlamın paylaşılan tabloyu bildirmesine gerek yoktur. Sadece DbSet<x>tanımını manuel olarak ekleyin . Bunu EF Designer'ın yaptıklarıyla eşleşen kısmi bir sınıfta yapıyorum.
Glen Little

Bana çok fazla baş ağrısı kurtardın, efendim! Kabul edilen cevap yerine somut bir çözüm sundunuz. Gerçekten takdir!
WoIIe

6

Hatırlatma: Birden fazla bağlamı birleştirirseniz, çeşitli işlevlerin tüm fonksiyonlarını RealContexts.OnModelCreating()tekliğinize yapıştırdığınızdan emin olun CombinedContext.OnModelCreating().

Sadece basamaklı silme ilişkilerimin neden modelBuilder.Entity<T>()....WillCascadeOnDelete();kodu gerçek bağlamımdan birleşik bağlamıma taşımadığımı keşfetmek için korunmadığı için zaman harcadım .


6
Kesme ve yapıştırma yerine OtherContext.OnModelCreating(), birleşik bağlamınızdan çağrı yapabilir misiniz ?
AlexFoxGill

4

Bu tasarıma rastladığımda bağırsaklarım bana aynı şeyi söyledi.

Bir veritabanına üç dbContexts olduğu bir kod tabanı üzerinde çalışıyorum. 3 dbcontexts'den 2'si, yönetimsel verileri sunduğu için 1 dbcontext'den gelen bilgilere bağlıdır. Bu tasarım, verilerinizi nasıl sorgulayabileceğiniz konusunda kısıtlamalar getirmiştir. Ben dbcontexts genelinde katılamaz bu sorunla karşılaştı. Bunun yerine yapmanız gereken iki ayrı dbcontex'i sorgulamak ve sonra bellekte birleştirme yapmak veya ikisinin kombinasyonunu sonuç kümesi olarak almak için her ikisini de yinelemek. Buradaki sorun, belirli bir sonuç kümesi için sorgulama yapmak yerine, şimdi tüm kayıtlarınızı belleğe yüklüyor ve daha sonra bellekteki iki sonuç kümesine karşı birleştirme yapıyorsunuz. Gerçekten işleri yavaşlatabilir.

Sorusunu sorarım "sadece yapabildiğin için değil mi? "

Bu tasarımla ilgili karşılaştığım sorun için bu makaleye bakın. Belirtilen LINQ ifadesi, farklı bağlamlarla ilişkili sorgulara başvurular içeriyor


3
Birden fazla bağlamımızın olduğu büyük bir sistem üzerinde çalıştım. Bulduğum şeylerden biri, bazen aynı DbSet'i birden çok bağlamda dahil etmeniz gerektiğiydi. Bir yandan bu bazı saflık endişelerini kırıyor, ancak sorgularınızı tamamlamanıza izin veriyor. Okumanız gereken bazı yönetici tablolarının olduğu bir durumda, bunları temel bir DbContext sınıfına ekleyebilir ve uygulama modülü bağlamlarınızda devralabilirsiniz. "Gerçek" yönetici içeriğinizin amacı, bunlara tüm erişim sağlamak yerine "yönetici tabloları için bakım sağlamak" olarak yeniden tanımlanabilir.
JMarsch

1
Ne için değer, ben her zaman buna değip değmediğini ileri geri gitti. Bir yandan, ayrı bağlamlarla, sadece bir modülde çalışmak isteyen bir geliştirici için daha az şey bilinir ve özel projeksiyonları tanımlamak ve kullanmak için daha güvenli hissedersiniz (çünkü diğer üzerindeki etkileri hakkında endişelenmediğiniz için modüller). Diğer yandan, bağlamlar arası veri paylaşmanız gerektiğinde bazı sorunlarla karşılaşırsınız.
JMarsch

1
Varlıkları her ikisine de dahil etmek zorunda değilsiniz, her zaman kimlikleri alabilir ve farklı bir bağlam için 2. bir sorgu yapabilirsiniz. Küçük sistemler için bu durum kötüdür, daha çok DB içeren çoklu tablo yapılarına sahip daha büyük DB'ler / sistemler için 2 sorgudan çok daha büyük ve daha zor bir problemdir.
user1496062

4

Esinlenen [@JulieLerman'ın DDD MSDN Mag Makalesi 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")
  {}
}   

"Yeni geliştirme yapıyorsanız ve Code First'in veritabanınızı sınıflarınıza göre oluşturmasına veya taşımasına izin vermek istiyorsanız, gereken tüm sınıfları ve ilişkileri içeren bir DbContext kullanarak bir" uber modeli "oluşturmanız gerekir. veritabanını temsil eden tam bir model oluşturun. Ancak, bu bağlam BaseContext'ten devralınmamalıdır. " JL


2

Önce kodda, birden çok DBContext ve sadece bir veritabanı olabilir. Yapıcıda bağlantı dizesini belirtmeniz yeterlidir.

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

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

Evet yapabilirsiniz, ancak farklı db bağlamlarından farklı varlıkları nasıl sorgulayabilirsiniz?
Reza

2

Başka bir "bilgelik" parçası. Ben internet ve dahili bir uygulama, hem de bakan bir veritabanı var. Her yüz için bir bağlam var. Bu disiplinli, güvenli bir ayrımcılığı korumama yardımcı oluyor.


1

Aynı veritabanında birden fazla DBContexts olma olasılığının iyi olduğunu düşündüğüm bir durumu paylaşmak istiyorum.

İki veritabanı ile bir çözüm var. Bunlardan biri kullanıcı bilgileri hariç alan adı verileri içindir. Diğeri yalnızca kullanıcı bilgileri içindir. Bu bölüm öncelikle AB Genel Veri Koruma Yönetmeliği tarafından yürütülmektedir . İki veritabanına sahip olarak, kullanıcı verileri güvenli bir yerde kaldığı sürece etki alanı verilerini (ör. Azure'dan geliştirme ortamım) serbestçe taşıyabilirim.

Şimdi kullanıcı veritabanı için EF üzerinden iki şema uyguladım. Bunlardan biri AspNet Identity çerçevesi tarafından sağlanan varsayılan ayardır. Diğeri, kullanıcıyla ilgili başka her şeyi kendi uygulamamızdır. Bu çözümü ApsNet şemasını genişletmeye tercih ediyorum, çünkü AspNet Identity'de gelecekteki değişiklikleri kolayca halledebiliyorum ve aynı zamanda ayırma programcılar için "kendi kullanıcı bilgilerimizin" tanımladığımız belirli kullanıcı şemasına girdiğini açıkça ortaya koyuyor .


2
Cevabımda herhangi bir soru göremiyorum. Tek bir soru sormuyorum! Aksine, tartışmanın konusunun mantıklı olduğu bir senaryoyu paylaşmak.
freilebt

0

Huh, her DB şeması için ayrı DB bağlamlarıyla ilgili bir sorun üzerinde oldukça fazla zaman harcadı, umarım başka birine yardımcı olacak ...

Geçenlerde 3 şemaları (DB ilk yaklaşım), biri kullanıcı yönetimi için bir veritabanı olan bir proje üzerinde çalışmaya başladı. Her ayrı şemadan iskele edilmiş bir DB bağlamı vardı. Elbette, kullanıcılar diğer şemalarla da ilişkiliydi, ör. şema KB, "tarafından oluşturulan", "son değiştiren" vb. içeren bir tablo Konusuna sahipti.

Bu nesneler ayrı ayrı C # olarak yüklendi, öncelikle konu 1 bağlamdan yüklendi, daha sonra kullanıcılar diğer db bağlamından kullanıcı kimlikleri aracılığıyla yüklendi - hoş değil, bunu düzeltmek zorunda! ( EF 6 ile aynı veritabanında birden çok dbcontex kullanmaya benzer )

İlk olarak, kimlik şemasından KB şemasına eksik FK talimatlarını, KB DB bağlamında EF modelBuilder'a eklemeye çalıştım. Sadece 1 bağlam varmış gibi, ama ben 2'ye ayırdım.

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

KB db bağlamı kullanıcı nesnesi hakkında herhangi bir bilgi içermediğinden, çalışmadı, postgres hata verdi relation "AppUsers" does not exist. Select deyimi şema, alan adları vb. Hakkında doğru bilgiye sahip değildi.

Neredeyse vazgeçtim, ama sonra bir anahtar "-d" çalışırken fark ettim dotnet ef dbcontext scaffold. -Data-ek açıklamaları için kısa - Modeli yapılandırmak için özellikleri kullanın (mümkünse). Atlanırsa, yalnızca akıcı API kullanılır. Bu anahtar belirtildiğinde, nesne özellikleri db bağlamında OnModelCreating()değil özniteliklerle birlikte nesnenin kendisinde tanımlanır .

Böylece EF, uygun alan adları ve şemaları ile uygun bir SQL ifadesi oluşturmak için yeterli bilgiye sahip oldu.

TL; DR: ayrı DB bağlamları aralarındaki ilişkileri (FK) iyi işlemez, her bağlamın yalnızca kendi varlıkları hakkında bilgi vardır. "-Data-ek açıklamaları" açıldığında dotnet ef dbcontext scaffold, bu bilgiler her ayrı bağlamda depolanır, ancak DB nesnelerinin kendisinde saklanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.