首先在 EF 代码中将文字或常量作为复合键的一部分

2024-01-08

我对实体框架的代码优先方法相对较新。我已经使用数据库优先方法有一段时间了,但是代码优先似乎更适合我当前正在开发的应用程序。我正在使用现有的 MS SQL 数据库,并且不允许我对数据库进行任何更改。我使用 Code First 的原因是 Fluent API 允许我动态地将表名分配给类。

也就是说,我遇到了一个困境,我需要在两个表之间分配关系。 ArCodes 表有一个由 CodeType 和 Code(均为字符串)组成的复合键。 CodeType 列确定代码的类型,Code 列是代码类型唯一的标识符。

public class ArCode {

    [Column("cod_typ", Order = 0), Key]
    public string CodeType { get; set; }

    [Column("ar_cod", Order = 1), Key]
    public string Code { get; set; }

    [Column("desc")]
    public string Description { get; set; }

}

另一个表“发票”需要与 ArCodes 表建立关系,以获取“运送途径”代码和“条款”代码。

public class Invoice {
    [Column("pi_hist_hdr_invc_no"), Key]
    public int InvoiceNumber { get; set; }

    [Column("shp_via_cod")]
    public string ShipViaCode { get; set; }

    public ArCode ShipVia { get; set; }

    [Column("terms_cod")]
    public string TermsCode { get; set; }

    public ArCode Terms { get; set; }

}

我想设置“ShipVia”属性和“Terms”属性的关系。但是,我不确定如何针对复合键的 CodeType 部分执行此操作。对于“ship via”代码,代码类型应为“S”,对于代码“term”代码,代码类型应为“T”。

我已经在 DB Context 中尝试了以下操作,但它不起作用:

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        // setup the table names
        modelBuilder.Entity<ArCode>().ToTable("ARCODS" + CompanyCode);
        modelBuilder.Entity<Invoice>().ToTable("IHSHDR" + CompanyCode);

        //
        // setup the relationships
        //

        // 1 Invoice <--> 0-1 Ship Via AR Codes
        modelBuilder.Entity<Invoice>()
            .HasOptional(invoice => invoice.ShipVia)
            .WithMany()
            .HasForeignKey(invoice => new { TheType = "S", invoice.ShipViaCode })
            ;

        base.OnModelCreating(modelBuilder);
    }

任何帮助,将不胜感激。

更新#1

好的,我将代码简化为最简单的形式,并遵循了 @GertArnold 提供的解决方案。

public abstract class ArCode {

    [Column("cod_typ")]
    public string CodeType { get; set; }

    [Column("ar_cod")]
    public string Code { get; set; }

    [Column("terms_desc")]
    public string TermsDescription { get; set; }

    [Column("terms_typ")]
    public string TermsType { get; set; }

    [Column("shp_via_desc")]
    public string ShipViaDescription { get; set; }

    [Column("tax_desc")]
    public string TaxDescription { get; set; }

}

public class TermsCode : ArCode { }
public class ShipViaCode : ArCode { }

public class Invoice {
    [Column("pi_hist_hdr_invc_no"), Key]
    public int InvoiceNumber { get; set; }

    [Column("hdr_invc_dat")]
    public DateTime InvoiceDate { get; set; }

    [Column("shp_via_cod")]
    public string ShipViaCode { get; set; }

    public ShipViaCode ShipVia { get; set; }

    [Column("terms_cod")]
    public string TermsCode { get; set; }

    public TermsCode Terms { get; set; }

    public Invoice() {
    }

}

public class PbsContext : DbContext {

    public DbSet<Invoice> Invoices { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {

        modelBuilder.Entity<Invoice>().ToTable("IHSHDR");

        modelBuilder.Entity<ArCode>().HasKey(r => r.Code).ToTable("ARCODS");

        modelBuilder.Entity<TermsCode>().Map(m => m.Requires("CodeType")
               .HasValue("T").HasColumnType("varchar").HasMaxLength(1).IsRequired())
               .ToTable("ARCODS");
        modelBuilder.Entity<ShipViaCode>().Map(m => m.Requires("CodeType")
               .HasValue("S").HasColumnType("varchar").HasMaxLength(1).IsRequired())
               .ToTable("ARCODS");

        base.OnModelCreating(modelBuilder);
    }

    public PbsContext()
        : base("name=PbsDatabase") {
    }
}

但是,以下代码会返回错误:

PbsContext context = new PbsContext();
var invoice = context.Invoices.OrderByDescending(r => r.InvoiceDate).FirstOrDefault();

错误 3032:从第 28 行开始映射片段时出现问题:映射条件成员“ArCode.cod_typ”,其条件不是“IsNull=False”。删除 ArCode.cod_typ 上的条件或将其从映射中删除。

如果我从 ArCode 类中删除“CodeType”列,并将所有“CodeType”引用更改为 OnModelCreating 事件中数据库列名称“cod_typ”,则上面的语句执行时不会出现错误。然而,尽管数据库中有匹配的记录,invoice.ShipVia 和invoice.Terms 都将为空事件。

更新#2

public abstract class ArCode {

    [Column("ar_cod")]
    public string Code { get; set; }

    [Column("terms_desc")]
    public string TermsDescription { get; set; }

    [Column("terms_typ")]
    public string TermsType { get; set; }

    [Column("shp_via_desc")]
    public string ShipViaDescription { get; set; }

    [Column("tax_desc")]
    public string TaxDescription { get; set; }

}

public class TermsCode : ArCode { }
public class ShipViaCode : ArCode { }

public class Invoice {
    [Column("pi_hist_hdr_invc_no"), Key]
    public int InvoiceNumber { get; set; }

    [Column("hdr_invc_dat")]
    public DateTime InvoiceDate { get; set; }

    [Column("shp_via_cod")]
    public ShipViaCode ShipVia { get; set; }

    [Column("terms_cod")]
    public TermsCode Terms { get; set; }

    public Invoice() {
    }

}

public class PbsContext : DbContext {

    public DbSet<Invoice> Invoices { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {

        modelBuilder.Entity<Invoice>().ToTable("IHSHDR");

        modelBuilder.Entity<ArCode>().HasKey(r => r.Code).ToTable("ARCODS");

        modelBuilder.Entity<TermsCode>().Map(m => m.Requires("CodeType")
               .HasValue("T").HasColumnType("varchar").HasMaxLength(1).IsRequired())
               .ToTable("ARCODS");
        modelBuilder.Entity<ShipViaCode>().Map(m => m.Requires("CodeType")
               .HasValue("S").HasColumnType("varchar").HasMaxLength(1).IsRequired())
               .ToTable("ARCODS");

        base.OnModelCreating(modelBuilder);
    }

    public PbsContext()
        : base("name=PbsDatabase") {
    }
}

现在,以下代码返回错误:

PbsContext context = new PbsContext();
var invoice = context.Invoices.OrderByDescending(r => r.InvoiceDate).FirstOrDefault();

EntityCommandExecutionException - 列名“ShipVia_Code”无效。列名称“Terms_Code”无效。


你想要的对于EF来说是不可能的。ArCode有一个复合键,因此与它的任何关联都必须使用两个属性。这意味着在Invoice你需要四个属性(两对)来引用两个ArCode对象。但是其中两个属性(那些用于CodeType) 没有被数据库中的列备份,因此 EF 无法映射它们。

但是……有一种方法可以帮助你。您可以创建两个派生类ArCode然后让Invoice参考单一财产协会的那些。但随后您必须从模型本身转移并通过定义单个键来愚弄 EF:

public abstract class ArCode { ... } // abstract!

public class TermsCode : ArCode { }

public class ShipViaCode : ArCode { }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Invoice>().ToTable("IHSHDR");

    modelBuilder.Entity<Invoice>().HasOptional(i => i.Terms).WithOptionalDependent().Map(m => m.MapKey("terms_cod"));
    modelBuilder.Entity<Invoice>().HasOptional(i => i.ShipVia).WithOptionalDependent().Map(m => m.MapKey("shp_via_cod"));

    modelBuilder.Entity<ArCode>().HasKey(a => a.Code).ToTable("ARCODS");
    modelBuilder.Entity<TermsCode>().Map(m => m.Requires("CodeType")
        .HasValue("T").HasColumnType("varchar").HasMaxLength(1).IsRequired())
        .ToTable("ARCODS");
    modelBuilder.Entity<ShipViaCode>().Map(m => m.Requires("CodeType")
        .HasValue("S").HasColumnType("varchar").HasMaxLength(1).IsRequired())
        .ToTable("ARCODS");

    base.OnModelCreating(modelBuilder);
}

public class Invoice
{
    [Column("pi_hist_hdr_invc_no"), Key]
    public int InvoiceNumber { get; set; }

    public ShipViaCode ShipVia { get; set; }

    public TermsCode Terms { get; set; }
}

如果您不需要插入,这可能对您有用ARCODS通过 EF 进行记录。它不允许您插入相同的记录Codes,尽管数据库允许。但我期待的内容ARCODS要相当稳定,也许用脚本来填充它就足够了。

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

首先在 EF 代码中将文字或常量作为复合键的一部分 的相关文章

  • LINQ to Entities - 无法将“System.DateTime”强制转换为 orderBy 中的“System.Object”类型

    我试图从传入的 Expression gt 中按日期订购实体的 IQueryable 并收到错误 无法将类型 System Nullable 1 转换为类型 System Object LINQ to Entities 仅支持转换实体数据模
  • 实体框架层次结构的代码优先映射

    我有一个看起来像这样的模型 public class Category public string Id get set public string Description get set public Category Parent ge
  • 在实体框架上克隆数据[重复]

    这个问题在这里已经有答案了 我正在创建软件 用户可以在其中基于旧产品创建新产品 现在我需要使用实体框架进行复制 克隆操作 首先我开始这样写 foreach sourcedata1 in table1 create new table cop
  • TransactionScope - 底层提供程序在 EnlistTransaction 上失败。 MSDTC 正在中止

    我们的团队遇到了一个问题 表现为 底层提供者在 EnlistTransaction 上失败 无法访问 已处置对象 对象名称 事务 这似乎是我们一开始使用就出现的交易范围 http msdn microsoft com en us libra
  • 实体框架中的重复键异常?

    我试图捕获当我将具有给定用户名的现有用户插入数据库时 引发的异常 正如标题所说 我正在使用 EF 当我尝试将用户插入数据库时 引发的唯一异常是 UpdateException 如何提取此异常以识别其是否是重复异常或其他异常 catch Up
  • 在 MVC 类上创建主键字段

    我是 MVC 和 C 新手 我只是偶然发现它并发现它很有趣 我遇到了一个不允许我继续的问题 这是我的代码 using System using System Collections Generic using System Linq usi
  • 如何检查 EntityTypeConfiguration 实例的成员配置?

    我正在使用 Entity Framework Code First 和继承自 EntityTypeConfiguration 的映射类 我这样做是为了封装我使用 Code First Fluent API 来配置实体的方法 我希望能够检查这
  • 如何为连接范围变量编写动态 where 子句

    我一直在使用 LINQ 进行查询 但遇到了动态 where 子句的问题 我想检查一个条件 如果为真 则将其添加到我的查询中 问题在于 where 正在使用我的连接之一中的范围变量之一 我的工作查询如下 var query from proj
  • 实体框架不将Where子句作为WHERE子句发送到SQL Server

    我有一个包含站点的简单数据库 每个站点都有一堆帖子 我正在尝试获取某个站点的所有 公共 帖子 我有一个名为 site 的变量 它已经是 EF 带来的实例 第一个显而易见的事情是 var posts from post in site Pos
  • 具有长期运行对象上下文的实体框架

    我对 WinForms 我敢说 WPF 中的 Linq to SQL 的主要烦恼之一是缺乏对长时间运行的数据上下文的支持 请参阅here http blogs msdn com dinesh kulkarni archive 2008 04
  • 了解 MVC-5 身份

    我创建了一个新的ASP NET MVC 5申请与Individual User Accounts然后更新了所有的Nuget packages在解决方案中 现在我尝试遵循一些教程中显示的一些指南 但遇到了一些问题 第一个是一个名为Applic
  • EF6“模型配置”已设置但未发现

    我有以下库 实体模型 dll 包含 POCO 类 实体DAL dll 引用EntityMODEL dll 实体服务 dll 引用 EntityMODEL dll 和 EntityDAL dll 实体测试 dll 引用 EntitySERVI
  • “等待操作超时”...但仅来自 .NET 客户端?

    我有一个查询 当从我的应用程序执行时会抛出 SqlException 0x80131904 超时已过期 操作完成之前超时时间已过 或者服务器没有响应 在 Visual Studio 中单步执行代码时 我遇到了同样的错误 但是 当使用相同的凭
  • Breezejs 加载具有相关数据的实体时出错

    毫无疑问 我在这里遗漏了一些明显的东西 所以也许互联网的集体力量可以向我指出这一点 我有一个代码优先的数据库结构 由用户 组和一个链接两者的 GroupUsers 表组成 EF 本身可以处理 n n 关系 但 Breezejs 需要显式地使
  • EF Core 迁移可以手动编辑吗?

    我在示例项目中使用 EF Core 2 0 和一些值对象配置 我修改代码并通过 CLI 命令行生成迁移 在最后一次迁移中 它没有像应有的那样添加新的数据库表 而是尝试将现有表彼此重命名并为现有表创建一个额外的表 我不明白其中的原因 问题是
  • 实体框架在不同的工作站上生成不同的查询

    我们在单个开发人员机器和一些客户端上遇到问题 单个 Linq 查询 生成两个不同的 SQL 查询 问题实际上是第二个查询有 firebird 不支持的 OUTER APPLY 语句 我们认为这不是代码问题 而是环境问题 但我会粘贴代码 li
  • 使用 linq-to-entities 将字符串转换为日期时间的大问题

    如何使用 linq toEntity 将字符串转换为日期时间 我收到以下查询 其中visit date列数据类型是字符串 var memberl from v in abc visits join m in abc members on v
  • 实体框架以错误的顺序插入子对象

    Question 为什么 EF 首先在它所依赖的对象 TimesheetActivity 之前插入具有依赖项的子对象 PersonnelWorkRecord 另外我有哪些纠正这个问题的选择 ERD 简化 This is predefined
  • 实体框架 - 悲观锁定

    我想做的基本上是NHibernate 做什么 http knol google com k nhibernate chapter 10 transactions and concurrency 10 282E 296 282E 29 28C
  • 对于相同的数据库对象,实体框架对象引用是否相同

    如果我从不同位置查询 逻辑上 在数据库中 相同的对象 实体框架是否返回相同的对象引用 例如 我查询了名为 Joe Black 的客户 并假设现在我知道数据库中只有一个 Joe Black Customer c select blabla w

随机推荐