我有以下 EF 代码第一个代码。我收到以下异常:
“GiftCouponPayment”不包含标识列。
表已在数据库中成功创建。然而,我怎样才能摆脱这个异常呢?另外,这个异常的原因是什么?
注意:只要保留域模型(首先使用代码描述)(并且可以查询数据),我就可以接受任何表模式。
继续这个异常之后,又出现了一个异常,如下:
保存未公开其关系的外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅内部异常。
{“违反主键约束'PK_dbo.PaymentComponent'。无法在对象'dbo.PaymentComponent'中插入重复的键。\r\n该语句已终止。”}
参考:
- 实体框架:将表拆分为多个表
Note:生成的数据库架构如下所示。
Code:
public class MyInitializer : CreateDatabaseIfNotExists<NerdDinners>
{
//Only one identity column can be created per table.
protected override void Seed(NerdDinners context)
{
//context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX IX_Payment_PayedTime ON Payment (PayedTime)");
context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('Payment', RESEED, 1)");
context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('GiftCouponPayment', RESEED, 2)");
context.Database.ExecuteSqlCommand("DBCC CHECKIDENT ('ClubCardPayment', RESEED, 3)");
}
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
//Fluent API - Plural Removal
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
//Fluent API - Table per Concrete Type (TPC)
modelbuilder.Entity<GiftCouponPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("GiftCouponPayment");
});
modelbuilder.Entity<ClubCardPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("ClubCardPayment");
});
}
public DbSet<GiftCouponPayment> GiftCouponPayments { get; set; }
public DbSet<ClubCardPayment> ClubCardPayments { get; set; }
public DbSet<Payment> Payments { get; set; }
}
public abstract class PaymentComponent
{
public int PaymentComponentID { get; set; }
public int MyValue { get; set; }
public abstract int GetEffectiveValue();
}
public partial class GiftCouponPayment : PaymentComponent
{
public override int GetEffectiveValue()
{
if (MyValue < 2000)
{
return 0;
}
return MyValue;
}
}
public partial class ClubCardPayment : PaymentComponent
{
public override int GetEffectiveValue()
{
return MyValue;
}
}
public partial class Payment
{
public int PaymentID { get; set; }
public List<PaymentComponent> PaymentComponents { get; set; }
public DateTime PayedTime { get; set; }
}
Client:
static void Main(string[] args)
{
Database.SetInitializer<NerdDinners>(new MyInitializer());
string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
GiftCouponPayment giftCouponPayment = new GiftCouponPayment();
giftCouponPayment.MyValue=250;
ClubCardPayment clubCardPayment = new ClubCardPayment();
clubCardPayment.MyValue = 5000;
List<PaymentComponent> comps = new List<PaymentComponent>();
comps.Add(giftCouponPayment);
comps.Add(clubCardPayment);
var payment = new Payment { PaymentComponents = comps, PayedTime=DateTime.Now };
db.Payments.Add(payment);
int recordsAffected = db.SaveChanges();
}
}
您没有为 TPC / TPT 映射指定 ID 字段。即使使用继承,您也需要在不运行 TPH 映射时执行此操作。 (要注意的是,我也不确定MapInheritedProperties()
call...这一般用于TPH...而不是TPT)
//Fluent API - Table per Concrete Type (TPC)
modelbuilder.Entity<GiftCouponPayment>()
.HasKey(x => x.PaymentComponentID)
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("GiftCouponPayment");
})
.Property(x => x.PaymentComponentID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
这需要在具体类型的每个类映射上。如果是我,我会选择 TPH 映射,其中 GiftCoupon 以及其他继承映射,这样您最终会得到 1 个表,使用鉴别器列来表示整个对象树。
无论如何...您的基类中缺少的另一件事是:
public byte[] Version { get; set; }
以及相关的映射:
Property(x => x.Version).IsConcurrencyToken()
这允许乐观并发。
希望这对您有所帮助,如果您需要进一步的帮助或说明,请告诉我。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)