用一张表存储多个表的数据

问题描述 投票:0回答:1

将 Entity Framework Core 与 Sqlite 结合使用,我有一个存储名为“Address”的地址数据的表。我希望在几个不同的表中使用这个表来存储地址。目前,我通过将 2 个字段直接添加到引用它的表中,使其适用于另一个表:

public int? ClientId { get; set; }
public Client? Client { get; set; }

问题是这只支持另一张表。我正在考虑修改 Address 类以将 BaseModel 列表存储在其中,如下所示:

public List<BaseModel> AddressObjects { get; } = new List<BaseModel>();

理论上,这将使我不必为我想要在 Address 类中支持的每个其他表添加字段。

我想知道解决此问题的最佳/正确方法是什么?

我当前的设置:

地址

public partial class Address: BaseModel
{
    public int Id { get; set; }    

    [ObservableProperty]
    private string? _unitNum;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Street Number is Required")]
    private string _streetNum;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Street Name is Required")] 
    private string _streetName;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Street Type is Required")]
    private string _streetType;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "Suburb is Required")]
    public string _suburb;

    [ObservableProperty]
    [NotifyDataErrorInfo]
    [Required(ErrorMessage = "City is Required")]
    private string _city;

    public int? ClientId { get; set; }
    public Client? Client { get; set; }
}

客户

public partial class Client : Person
{
    public int Id {  get; set; }    

    public Address BusinessAddress { get; set; } = null;    
}

供应商

public partial class Supplier : Person
{
    public int Id {  get; set; }    

    public string SupplierType { get; set; }

    public Address ShopAddress { get; set; } = null;    
}

移动

public partial class Shift : BaseModel
{
   public int Id { get; set;}
   public Address ShiftLocation {get; set;}
}

 public abstract partial class Person: BaseModel
 {
     public int Id { get; set; }

     [ObservableProperty]
     [NotifyDataErrorInfo]
     [Required(ErrorMessage = "First Name is Required")]
     private string _firstName;

     [ObservableProperty]
     [NotifyDataErrorInfo]
     [Required(ErrorMessage = "Last Name is Required")]
     private string _lastName;
}
c# sqlite entity-framework-core
1个回答
0
投票

您可以使用单向多对一模型,其中供应商、客户和轮班等表每个都包含一个AddressId。地址不需要反向导航属性。您可以在每个实体中使用影子属性来避免暴露 AddressId:

public class Supplier : Person
{
    public virtual Address ShopAddress { get; set; }
}

然后在配置中:

modelBuilder.Entity<Supplier>()
   .HasOne(x => x.ShopAddress)
   .WithMany()
   .HasForeignKey("AddressId"); // The FK name in the Supplier table.

这种方法的潜在问题是,它是多对一,意味着两个或多个供应商可以引用相同的地址,并且供应商和客户等可以引用相同的地址。可以通过对表的 AddressId 进行唯一约束来强制将地址限制为给定表中的单行,但强制地址不在表之间共享并不是一件简单的事情。在这种情况下,最好使用特定的地址表或拥有的实体。 (与所有者相同的表,或每个所有者单独的地址表)

如果您确实打算在所有者实体之间共享地址,则双向链接将不会真正起作用,除非左侧的所有实体本质上都使用 EF 中的 TPH 或 TPT 继承来继承相同的基类。如果您想在供应商、客户等之间共享地址记录,您只需做一点工作即可查询每个潜在的拥有实体:

var clients = Context.Clients.Where(x => x.AddressId == addressId).ToList();
var suppliers = Context.Suppliers.Where(x => x.AddressId == addressId).ToList();
// ...

如果您想将它们整齐地放入一个列表中,您可以使用

.Select(x => new AddressOwner { /* populate common descriptive fields */ }).ToList();
将它们投影到一个通用的描述性类中,并使用
Union()
将结果列表放在一起。如果 AddressId 已建立索引,那么运行的查询将相当快、影响低。

© www.soinside.com 2019 - 2024. All rights reserved.