实体框架多租户共享数据架构:单列、多个外键

2023-11-25

我有以下数据结构:

//property Notification
abstract class BindableBase { }
//base class for all tenant-scoped objects
abstract class TenantModelBase : BindableBase 
{ 
  int TenantId;
} 

abstract class Order : TenantModelBase 
{
   Customer Customer; //works: mapped using TenantId and CustomerId
   Product Product; //again, works with TenantId and ProductId
   string ProductId;
   string CustomerId;
}
class Customer: TenantModelBase 
{
   string CustomerId; 
}

class Product  : TenantModelBase 
{
   string ProductId;
}

class SpecialOrder : Order
{
    OtherClass OtherClass; //this fails!, see below
    string OtherClassId;
}
class SuperSpecialOrder : SpecialOrder {  }

class OtherClass  : TenantModelBase 
{
    string OtherClassId;
}

我收到以下错误:

外键组件“TenantId”不是声明的属性 输入“特殊订单”。验证是否未明确排除 来自模型并且它是有效的原始属性。

使用 Fluent Api 配置时出现错误:

        config.HasRequired(p => p.OtherClass)
            .WithMany(oc => oc.SpecialOrders)
            .HasForeignKey(p => new {  p.TenantId, p.OtherClassId});

如果没有OtherClass参考文献SpecialOrder我可以毫无问题地自由创建对象(包括SpecialOrder, SuperSpecialOrder etc).

有人知道发生了什么事吗?我在这里迷路了:(

Edit我在其他问题中看到人们从表中删除 TenantId,这不是一个选项,因为主键在租户之间不是唯一的,并且我们希望保留共享数据架构。

我知道解决方法是在 SpecialOrder 类中添加第二个 TenantId,但这对我来说似乎不合逻辑。


您是否正在尝试执行 TPT,其中有一个单独的订单/租户表?如果是这样,我认为另一张海报是正确的,并且 EF 中存在错误。

如果客户/产品是您的基础映射类,这可能适合您。

当我创建数据库时发生的事情是它试图映射抽象 Order 类。

通过增加:

modelBuilder.Ignore<Order>();

由于 MapInheritedProperties,构建器保留了映射的属性,但没有创建表,以便正确创建所有 FK。

我假设您想要为每个类使用单独的表,就像上面的相关帖子一样,并且不映射您的抽象表。

整个模型:

 public abstract class BindableBase { }
   //base class for all tenant-scoped objects
   public abstract class TenantModelBase : BindableBase
   {
      [Key]
      public virtual int TenantId { get; set; }
   }

   public abstract class Order : TenantModelBase
   {
      public Customer Customer { get; set; } //works: mapped using TenantId and CustomerId
      public Product Product { get; set; } //again, works with TenantId and ProductId
      public string ProductId { get; set; }
      public string CustomerId { get; set; }
   }
   public class Customer : TenantModelBase
   {
      [Key]
      public string CustomerId { get; set; }
   }

   public class Product : TenantModelBase
   {
      [Key]
      public string ProductId { get; set; }
   }

   public class SpecialOrder : Order
   {
      [Key]
      public int SpecialOrderId { get; set; }
      public OtherClass OtherClass { get; set; } //this fails!, see below
      public string OtherClassId { get; set; }
   }
   public class SuperSpecialOrder : SpecialOrder { }

   public class OtherClass : TenantModelBase
   {
      public string OtherClassId { get; set; }
      public ICollection<SpecialOrder> SpecialOrders { get; set; }
   }



   public class Model : DbContext
   {
      public DbSet<Customer> Customers { get; set; }
      public DbSet<Product> Products { get; set; }
      public DbSet<SpecialOrder> SpecialOrders { get; set; }
      public DbSet<SuperSpecialOrder> SuperSpecialOrders { get; set; }

      public DbSet<OtherClass> OtherClasses { get; set; }

      protected override void OnModelCreating( DbModelBuilder modelBuilder )
      {
         modelBuilder.Entity<OtherClass>()
            .HasKey( k => new { k.TenantId, k.OtherClassId } );

         modelBuilder.Entity<Customer>()
            .HasKey( k => new { k.TenantId, k.CustomerId } );

         modelBuilder.Entity<Product>()
            .HasKey( k => new { k.TenantId, k.ProductId } );


         modelBuilder.Entity<SpecialOrder>()
            .Map( m =>
                     {
                        m.MapInheritedProperties();
                        m.ToTable( "SpecialOrders" );
                     } );

         modelBuilder.Entity<SpecialOrder>().HasKey( k => new { k.TenantId, k.SpecialOrderId } );

         modelBuilder.Entity<SuperSpecialOrder>()
          .Map( m =>
          {
             m.MapInheritedProperties();
             m.ToTable( "SuperSpecialOrders" );
          } )
          .HasKey( k => new { k.TenantId, k.SpecialOrderId } );

         modelBuilder.Entity<SpecialOrder>()
          .HasRequired( p => p.OtherClass )
          .WithMany( o => o.SpecialOrders )
          .HasForeignKey( p => new { p.TenantId, p.OtherClassId } );

         modelBuilder.Entity<Order>()
            .HasRequired( o => o.Customer )
            .WithMany()
            .HasForeignKey( k => new { k.TenantId, k.CustomerId } );

         modelBuilder.Entity<Order>()
          .HasRequired( o => o.Product )
          .WithMany()
          .HasForeignKey( k => new { k.TenantId, k.ProductId } );

         modelBuilder.Ignore<Order>();


      }
   }

Created Database: enter image description here

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实体框架多租户共享数据架构:单列、多个外键 的相关文章

随机推荐

  • 在 Google Sheets 自定义函数中抛出自定义异常和错误消息?

    In 谷歌表格 与Excel等 如果用户在公式中输入错误的输入 错误代码将打印在有问题的单元格中 并且一个小弹出窗口提供有关错误的更多详细信息 所以如果我输入 SQRT 1 NUM 打印在单元格中 并且弹出窗口解释该值需要等于或大于 0 如
  • 使用 RestKit 进行外键关系映射

    我对 RestKit 完全陌生 并且有些挣扎 JSON teams id 1 name Team A id 2 name Team B users id 1 name cameron teamId 1 id 2 name
  • 如何在jq中添加索引

    我想使用 jq 映射我的输入 a b 输出 name a index 0 name b index 1 我已经到达 0 as i def incr i i 1 name index incr 其输出 name a index 1 name
  • 如何解决错误 LNK2019

    我正在用 C 发送一封简单的电子邮件 我从下面的链接下载了一个示例 C 程序 http cboard cprogramming com cplusplus programming 125655 sending simple email cp
  • 如何以编程方式在另一个 shapeDrawable 内绘制较小的 ShapeDrawable

    我试图在另一个圆圈内画一个较小的圆圈 这看起来很简单 但我遇到了麻烦并且找不到答案 我使用的代码是 ShapeDrawable biggerCircle new ShapeDrawable new OvalShape biggerCircl
  • iPhone:绘制一条曲线直到它变成一个圆形动画

    我希望画一条曲线 直到它旋转一周并连接成一个完整的圆 只是圆的轮廓 没有填充 这必须在几秒钟内进行动画处理 有人能指出我正确的方向吗 我已经问过一个类似的问题但我的措辞不正确 所以每个人都很难理解我的意思 因此它迷失在问题的海洋中 非常感谢
  • 在 spring 中销毁另一个用户的会话

    在我的应用程序中 我有一个可以删除用户的管理员 因此 当我从管理会话中删除用户时 我希望删除的用户应该自动注销 我知道我删除的用户的会话 ID 但我不知道如何使用会话 ID 使会话无效 我想要类似的东西 invalidate Session
  • ASP.Net MVC 中的 PageMethods

    我发现 ASP Net PageMethods 非常方便且易于使用 但我刚刚开始使用 MVC 进行开发 不确定如何使用它们 相当于什么PageMethods MyFunction 在 MVC 中 MyFunction 是控制器操作 我知道我
  • VB6:跨所有用户会话的单实例应用程序

    我有一个应用程序需要成为 Windows PC 上所有用户会话的单实例应用程序 到目前为止 我的研究主要集中在使用互斥锁来完成此任务 但我遇到了一个问题 我不确定这是否真的是一个问题 我相信这确实是一个最佳实践问题 首先是代码 Privat
  • javascript 如何创建引用

    您能否提出任何解决方法来使用闭包或任何其他技巧来实现对变量的引用 createReference function TODO how to implement var x 5 var refX createReference x could
  • 如何将 Bootstrap 4 导航栏中的品牌徽标设置到左边缘?

    我有一个徽标 如下所示
  • RabbitMQ 使用自定义标头来存储消息参数

    我是 RabbitMQ 的新手 我对文档有些迷失 目前 作为一个例子 我正在尝试构建一个侦听队列的小型邮件服务 但我有点卡在应该将服务的参数放在哪里 目的地 主题 我应该将它们放在消息中的某种编码格式 json 中 还是应该使用标头结构 如
  • 单击地图注释时显示另一个视图

    我有一张只有一个注释的地图 我创建了一个简单的类 我希望它在用户单击注释时显示 问题是 当我单击注释时什么也没有发生 这是我的代码 void reverseGeocoder MKReverseGeocoder geocoder didFin
  • python中的子句提取/长句分割

    我目前正在开展一个涉及句子向量的项目 来自 RoBERTa 预训练模型 当句子很长时 这些向量的质量较低 并且我的语料库包含许多带有子句的长句子 我一直在寻找子句提取 长句分割的方法 但令我惊讶的是 没有一个主要的 NLP 软件包 例如 s
  • 如何将 javascript 字符串分解为每五个单词换行一次?

    我有一个不寻常的请求 给定一个如下所示的字符串 var a This is a sentance that has many words I would like to split this to a few lines 我需要每五个单词插
  • 隐式 DataTemplate 不起作用

    为什么下面隐含DataTemplate不行 仅内嵌注释DataTemplate将工作 注意 如果我删除两者DataTemplates 我看到一个字符串表示形式ProductListView完整类型名称
  • 日志文件中写入什么内容?

    我的问题很简单 将什么写入日志 有什么约定吗 我必须放入什么 由于我的应用程序必须发布 我希望有友好的日志 大多数人都可以阅读这些日志 而无需询问它是什么 我已经有了一些想法 比如时间戳 每个函数 方法的唯一标识符等 我想要几个日志级别 例
  • Android USB鼠标右键单击正确行为(ICS)

    插入 android ics 的 USB 鼠标的右键单击是否始终指定为 后退 按钮 我有一台平板电脑 但没有 我想删除状态栏 并且仍然能够通过 USB 鼠标使用平板电脑 有谁知道在哪里 如何配置 android 中的行为 迟到的答案 但答案
  • C++ 重写异常::what()

    我有一个自定义异常 class RenterLimitException public std exception public const char what 重写what 的正确方法是什么 现在 我在头文件中创建了这个自定义 并希望覆盖
  • 实体框架多租户共享数据架构:单列、多个外键

    我有以下数据结构 property Notification abstract class BindableBase base class for all tenant scoped objects abstract class Tenan