gpt4 book ai didi

entity-framework - 首先在 EF 代码中作为组合键的一部分的文字或常量

转载 作者:行者123 更新时间:2023-12-04 08:33:24 27 4
gpt4 key购买 nike

我对 Entity Framework 的代码优先方法比较陌生。我已经使用 Database First 方法有一段时间了,但 Code First 似乎更适合我目前正在开发的应用程序。我正在使用现有的 MS SQL 数据库,并且不允许对数据库进行任何更改。我使用 Code First 的原因是因为 Fluent API 允许我为类动态分配表名。

也就是说,我有一个困境,我需要在 2 个表之间分配关系。一张表 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; }

}

另一个表 Invoices 需要与 ArCodes 表的“ship via”代码和“terms”代码建立关系。
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”,代码“terms”代码,代码类型应该是“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();

error 3032: Problem in mapping fragments starting at line 28:Condition member 'ArCode.cod_typ' with a condition other than 'IsNull=False' is mapped. Either remove the condition on ArCode.cod_typ or remove it from the mapping.



如果我从 ArCode 类中删除“CodeType”列并在 OnModelCreating 事件中将所有“CodeType”引用更改为“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 - Invalid column name 'ShipVia_Code'. Invalid column name 'Terms_Code'.

最佳答案

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

但是......有一种方法可以帮助你。您可以从 ArCode 创建两个派生类并让 Invoice指的是单一属性(property)协会的那些。但是,您必须从模型本身转移并通过定义单个键来愚弄 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记录。它不允许您插入具有相同 Code 的记录s,尽管数据库允许它。但我期望 ARCODS 的内容非常稳定,也许用脚本填充它就足够了。

关于entity-framework - 首先在 EF 代码中作为组合键的一部分的文字或常量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11526497/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com