EF Code首先没有为ICollection生成表
本文关键字:string ICollection Code EF | 更新日期: 2023-09-27 18:15:17
我希望下面的ICollection属性在我的一个数据类中(让我们称之为"Foo")
public class Foo
{
[Key]
public int FooId { get; set; }
public string SomeValueOrOther { get; set; }
public virtual ICollection<string> AllowedBars { get; set; }
}
我可以在使用实体上下文时添加字符串值,但它们不会"去任何地方"。换句话说,没有生成表来表示这种关系,因此没有保存任何值。我期望的是一个有两列的表,一列用于"FooId",一列用于"AllowedBar",EF将其自动映射到集合(就像它在复杂类型中所做的那样)。
由于这种情况没有发生,我不得不创建一个名为"FooAllowedBar"的类,并具有上面描述的两个属性。
这让我很不高兴,因为它是我在整个项目中唯一的"连接"类型类。它工作,当然,所以一个框被选中,但有人知道一种方法,让EF生成一个表的字符串集合关系吗?(或int,或datetime等)
很可能,从EF(仍然!)上的一点信息来看,这种类型的功能(尚未)被支持。我只是想接近一个明确的答案。
提前感谢,Rob
EF只能处理实体类。每个实体类必须有定义的主键,所以在您的场景中最小值是:
public class StringData
{
public int Id { get; set; }
public string Data { get; set; }
}
或者更糟
public class StringData
{
[Key]
public string Data { get; set; }
}
现在可以定义StringData的集合,将其映射为相关的表:
public virtual ICollection<StringData> AllowedBars { get; set; }
我知道这不是在所有情况下的最佳实践,但我认为在某些情况下,在列中存储逗号分隔的数组列表是解决此问题的好方法。
条件包括:
- 列表不会很长
- 您不需要根据该列表中的值搜索实体
如果一个实体中有多个字符串列表,这会创建大量的连接,这也是一个好主意。
在这些情况下,我将通过为列表设置两个属性来解决它。一个是EF使用的逗号分隔的列表,另一个是在访问列表中的项目时可以使用的列表,如:[NotMapped]
public List<String> AllowedBars { get; set; }
/// <summary>
/// Comma seperated list of AllowedBars
/// </summary>
public String AllowedBarsList
{
get { return String.Join(",", AllowedBars); }
set
{
if (String.IsNullOrWhiteSpace(value))
{
AllowedBars.Clear();
}
else
{
AllowedBars = value.Split(',').ToList();
}
}
}
你需要在构造函数中将AllowedBars初始化为一个空列表
你不需要使用[NotMapped]属性,因为这个集合无论如何都不会被使用,但我认为它使意图更清晰。
这行不通。这样做的原因是,使用关系数据库时,您不能真正将数组或集合保存在字段中。由于类中的每个属性都将映射到数据库字段,因此访问集合的唯一方法是通过一对多关系。所以你需要连接。所以这不是EF的限制,而是关系数据库的限制。
有人通过将XML或CSV保存到表中的字符串字段来解决这个问题。但是这被认为是非常糟糕的风格,所以不要这样做。我建议你接受加入。反正也不会伤害任何人。您没有适当地定义您的类表。假设你有两个表格Foo和FooBar。Foo和FooBar是一对多的关系。然后,您将按照如下方式定义这些类。
Foopublic class Foo
{
public int FooId { get; set; }
public string SomeValue { get; set; }
public virtual ICollection<FooBar> FooBars { get; set; }
}
FooBar
public class FooBar
{
public int FooBarId { get; set; }
public string SomeProperty { get; set; }
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
}
这将创建两个表,Foo有两列,FooBar有3列,包括FooId描述Foo和FooBar之间的一对多