自引用实体框架模型
本文关键字:模型 框架 实体 自引用 | 更新日期: 2023-09-27 18:29:01
提前感谢您的帮助。
我正试着和一个朋友为一个小rpg制作一个数据库。到目前为止,我们一直在跟踪JSON文件中的攻击类型(我的朋友不懂技术,所以我们早期只对纯文本文件进行了妥协)。我想让他成为一个网站,这样他就可以更容易地编辑我们的想法之间的关系(类型、怪物物种、可能的攻击等)
所以我从中提取的数据看起来是这样的:
{
"name": "water",
"isElement": true,
"defendAgainst": [
"fire",
"undead",
"atomic",
"food"
],
"immuneTo": [
"water"
],
"weakTo": [
"electric",
"zoetic",
"sonic",
"eldritch"
]
}, ... and so on
在这个例子中,水是一种元素,它可以防御火型,对水攻击免疫,对声波攻击较弱。
我做了一个将JSON转换为Object的东西,最后得到了这样的东西:
public class monsterType
{
[Key]
public string name { get; set; }
public ICollection<monsterType> weakTo { get; set; }
public ICollection<monsterType> immuneTo { get; set; }
public ICollection<monsterType> defendAgainst { get; set; }
public bool isElement { get; set; }
}
我通过以下操作从JSON进行翻译:
// set up the types references
foreach (typeJSON ty in typeListFromFile){
monsterType realTypeReference = lookUpMonsterTypeFromJSONtype(ty, realTypes);
//convert those lists
ICollection<monsterType> mtWTs = ty.weakTo.Select(w => lookUpMonsterTypeFromName(w, realTypes)).ToList();
ICollection<monsterType> mtDAs = ty.defendAgainst.Select(w => lookUpMonsterTypeFromName(w, realTypes)).ToList();
ICollection<monsterType> mtITs = ty.immuneTo.Select(w => lookUpMonsterTypeFromName(w, realTypes)).ToList();
//set them on the real type reference
realTypeReference.weakTo = mtWTs;
realTypeReference.defendAgainst = mtDAs;
realTypeReference.immuneTo = mtITs;
}
数据进入monsterType的实例很好。我和40个怪物坐在一起,他们互相指代都很棒。
我正在使用这个项目来自学MVC和实体框架(代码优先?),尽管我过去曾像Flask一样玩过,但我在C#.net领域有点力不从心,所以如果我遗漏了一些明显的东西,请原谅我。
我已经建立了一个与SQL Server数据库的数据库连接,它正在创建realTypes表OK——但它缺少immuneTo、weakTo和defensedAgains列,我认为这是因为这都是自引用的。
好吧,所以我做了一个数据上下文:
public class monsterDataContext : DbContext
{
public monsterDataContext() : base("name=blood")
{
}
public DbSet<monsterType> Types { get; set; }
}
我只是循环浏览我的列表并保存我的更改:
using (var theDB = new monsterDataContext())
{
foreach (monsterType ty in realTypes)
{
theDB.Types.Add(ty);
}
theDB.SaveChanges();
}
当我这样做时,它在DB.SaveChanges()上出错,带有:
违反了多重性约束。角色关系的'monsterType_defendAgainst_Source'"ParseMonsterYaml.monsterType_defendAgainst"具有多重性1或0..1.
我不太清楚为什么这是个问题?
它还创建了表,这很好,但列并没有真正达到我的期望:
name, isElement, monsterType_name, monsterType_name1, monsterType_name2
但这并不像错误那么重要。没有数据被加载到表中,它是空的。
我做错了什么?一些基本的东西?我是不是遇到了什么可怕的事?有更好的方法吗?
当您想要自定义列名时,您必须告诉EF它们的名称,您可以按如下方式执行。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MonsterType>()
.HasRequired(t => t.DefendAgainst)
.WithMany()
.Map(configuration => configuration.MapKey("DefendAgainst"));
modelBuilder.Entity<MonsterType>()
.HasRequired(t => t.ImmuneTo)
.WithMany()
.Map(configuration => configuration.MapKey("ImmuneTo"));
modelBuilder.Entity<MonsterType>()
.HasRequired(t => t.WeakTo)
.WithMany()
.Map(configuration => configuration.MapKey("WeakTo"));
base.OnModelCreating(modelBuilder);
}
关于您的错误,默认情况下,您的一对多关系列创建为NOT NULL,这就是为什么当您保存缺少的数据时,它违反了SQL约束。如果DefendAgaint、WeekTo和ImmuneTo可以为null,那么在上面的代码中,将.HasRequired替换为.HasOptional,如下所示
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MonsterType>()
.HasOptional(t => t.DefendAgainst)
.WithMany()
.Map(configuration => configuration.MapKey("DefendAgainst"));
modelBuilder.Entity<MonsterType>()
.HasOptional(t => t.ImmuneTo)
.WithMany()
.Map(configuration => configuration.MapKey("ImmuneTo"));
modelBuilder.Entity<MonsterType>()
.HasOptional(t => t.WeakTo)
.WithMany()
.Map(configuration => configuration.MapKey("WeakTo"));
base.OnModelCreating(modelBuilder);
}
这将生成此SQL
create table [dbo].[MonsterTypes] (
[Name] [nvarchar](128) not null,
[IsElement] [bit] not null,
[DefendAgainst] [nvarchar](128) null,
[ImmuneTo] [nvarchar](128) null,
[WeakTo] [nvarchar](128) null,
primary key ([Name])
);
alter table [dbo].[MonsterTypes] add constraint [MonsterType_DefendAgainst] foreign key ([DefendAgainst]) references [dbo].[MonsterTypes]([Name]);
alter table [dbo].[MonsterTypes] add constraint [MonsterType_ImmuneTo] foreign key ([ImmuneTo]) references [dbo].[MonsterTypes]([Name]);
alter table [dbo].[MonsterTypes] add constraint [MonsterType_WeakTo] foreign key ([WeakTo]) references [dbo].[MonsterTypes]([Name]);
希望我已经理解了这个权利!