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 Code首先没有为ICollection<string>生成表

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是一对多的关系。然后,您将按照如下方式定义这些类。

Foo

public 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之间的一对多