【问题标题】:EF Core 5.0 relational from non-relational db来自非关系数据库的 EF Core 5.0 关系
【发布时间】:2020-12-22 10:36:44
【问题描述】:

这就是问题所在。

我有一个来自旧 COBOL 软件的古老数据库(txt 文件)。

我想要什么

  • 在不更改原始数据的情况下关联下面列出的对象。

背景

DB 是 MS-SQL。每个导入的对象都有一个唯一的 id(数据库生成)。旧 COBOL 软件中实际组合对象的“外键”(“NonUniqueItemProperty”)不是唯一的。 (这就是为什么我不能在表之间创建关系)

我的问题是,这可能吗?

目前我在查询中加入表格

select item.*,owner.* from Items item
INNER JOIN Ownership ownership on item.NonUniqueItemProperty=ownership.NonUniqueItemProperty
INNER JOIN Owner owner on ownership.OwnerIdNo=owner.OwnerIdNo

此查询返回匹配 (item-->ownerCount)*(item-->count) 的结果集。然后我使用 linq 按 Item.NonUniqueItemProperty 对它们进行分组,并为每个 Item 设置所有者。

对象:

    public class Item
    {
        pullic int Id {get;set;} // database generated, non-related to original data
        public string NonUniqueItemProperty {get;set;} //sadly this is the identifier
        public virtual ICollection<Ownership> Ownerships { get; set; }
    }
    
    public class Ownership
    {
        pullic int Id {get;set;} // database generated, non-related to original data
        public virtual Item Item { get; set; }
        public virtual Owner Owner { get; set; }
        public string NonUniqueItemProperty {get;set;}
        public string OwnerIdNo {get;set;}
    }
    
    public class Owner
    {
        pullic int Id {get;set;} // database generated, non-related to original data
        public virtual ICollection<Ownership> Ownerships { get; set; }
        public string OwnerIdNo {get;set;}
    }

我尝试在 fluent api 中创建关系:

    item.HasMany<Ownership>(i => i.Ownerships)
                .WithOne(ow => ow.Item)
                .HasPrincipalKey(i=>i.NonUniqueItemProperty)
                .HasForeignKey(ow=>ow.NonUniqueItemProperty);

目前没有错误,但导航属性为空。

编辑

在这之后,我意识到这个表达式返回了一个带有 null Ownership 导航的 Item 实体。结果集返回了我正在寻找的内容,因此导航可用于过滤项目集!

var resultSet = ctx.Items.Where(
             i => i.Ownerships.Any(
                     ow => ow.Owner.OwnerIdNo=="P12345"));

【问题讨论】:

  • 为什么使用 NonUniqueItemProprty 作为键?我建议始终在每个对象上使用 ID 作为键。我还认为,因为您使用 FluentAPI 并说“HasMany”和“WithOne”,所以您已经将对象项和所有权链接在一起。使用 ID EntityFramework 将知道什么属于一起。我不确定它对字符串作为“ID”的作用
  • @JelleSchräder,根据帖子解释,这不是我设计的数据库。实际对象有一个由数据库生成的 Id 字段,但我不使用它,因为我从纯文本文件导入的数据没有意义。而且我不允许更改原始数据。
  • “From cobol” 短语实际上与“COBOL 数据库”不完全匹配,是吗?此外,标题声明“来自非关系数据库的关系”,我在帖子中声明“导航属性为空”,因此其他属性不为空。因此,支持数据库。请考虑看这张图片:link
  • @Hasan 首先,冷静下来,不要太私人化。评论是为了澄清,这里的人通常是善意的。 Get 是这里这个领域中最合理和最有建设性的人和专家之一,所以请确保他将* 为您提供解决方案(如果存在)。但这已经足够了,现在是具体的主题。一般来说,您要问的问题是不可能的,因为如果Item.NonUniqueItemProperty 不是唯一的,那么Ownership.NonUniqueItemProperty 连接可能会产生不止一个多,因此逻辑关系是to many,因此不能被代表
  • ... 甚至在逻辑上使用参考导航属性。但我想知道您如何将Item 类映射为无键实体?或者通过欺骗 EFC Item.NonUniqueItemProperty 是一个键(唯一)来“常规”实体?

标签: c# orm ef-fluent-api non-relational-database ef-core-5.0


【解决方案1】:

我设法通过 Eager Loading 在解释 Here 中获得导航属性

通过在查询末尾添加Include(i=&gt;i.Ownership).ThenInclude(ow=&gt;ow.Owner)

但是根据两位领域专家的建议,这不应该起作用,我不打算在代码中实现它,这在 EF 的更高版本中也不起作用。

编辑

这是真正的性能杀手!通过编写上面的 sql-query,TOP 150 Items 消耗 120-150 ms,这一项是 2.500-4.000 ms (query.Take(100))。

(项目数:350K, 拥有数:390K)

【讨论】:

    猜你喜欢
    • 2021-05-20
    • 1970-01-01
    • 2010-09-08
    • 2021-11-25
    • 2021-05-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多