我刚刚在Table per Type
/ TPT和歧视者专栏上阅读了不少帖子,但是,在我的情况下,我并不是真的更聪明。
举个例子:我有一个名为Foo
的模型的MVC应用程序。这有一个名为Bar
的属性,在其他地方存储为一个。
我是唯一一个使用此应用的人,我不想花很多时间在上面,所以我只想要最快捷的方式将项目添加到Bar
的列表中。因此,我创建了一个名为FooViewModel
的新类,它派生自Foo
,并且有一个名为BarTemp
的字符串属性。
基本思想是我可以在标准文本字段中键入111, 222 , 333,444
并让编辑/创建控制器清除空白并分成逗号上的列表。
我能弄清楚的是,视图模型永远不会写入EF,因此,为什么要创建鉴别器列。
当我尝试搭建迁移时,它似乎尝试将BarTemp
添加到数据库。
我已经创建了一个名为相同的新类型,但是我只是将Foo
和BarTemp
作为属性,而不是派生,而是按预期工作,但是,我仍然没有'了解发生的事情,并希望了解更多。
答案 0 :(得分:2)
这是因为EntityFramework解析了层次结构。仅仅因为您当前的代码没有保存BarTemp
,所以没有明确阻止您写作:
context.Bars.Add(new BarTemp());
EntityFramework无法检测上述内容。因此,它可以安全地运行,并假设如果您从实体继承,您的子类也是一个实体。这是一个正确的假设 - 你不应该让视图模型继承自实体。他们也不应该是财产。我真的不确定 你是如何设置当前代码的,但这些类应该是完全不同的。例如,它应该类似于:
class BarTemp
{
public string BarId { get; set; }
public string Foos { get; set; }
}
class Bar
{
public string BarId { get; set; }
public ICollection<Foo> Foos { get; set; }
}
class Foo
{
public string Id { get; set; }
public Bar Bar { get; set;
}
您的视图模型应该对实体一无所知,实体应该对视图模型一无所知。接受输入的代码应该将视图模型转换为实体。例如:
private void Update(BarTemp barTemp)
{
var bar = context.Bars.GetById(barTemp.BarId);
foreach (var foo in barTemp.Foos.Split(","))
{
var foo = context.Foos.GetById(foo);
bar.Foos.Add(foo);
}
context.Save();
}
不要将上述内容作为优秀代码的示例 - 效率极低 - 但它应该向您展示转换应在何处发生的示例,以及如何保留实体和查看模型分开。