EF Code First不为ICollection生成表<string> </string>

时间:2011-11-20 13:11:19

标签: c# asp.net-mvc entity-framework ef-code-first

我想在我的一个数据类中使用下面的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”的类。

这让我很不高兴,因为它是我在整个项目中唯一的“join”类型。当然,它可以工作,所以一个方框被勾选,但有没有人知道如何让EF为字符串集合关系生成一个表? (或int,或datetime等)

很可能,从EF上的小信息(仍然!)来看,这种功能还没有得到支持。我想接近一个明确的答案。

非常感谢, 罗布

4 个答案:

答案 0 :(得分:17)

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; }

答案 1 :(得分:3)

我知道这不是所有情况下的最佳做法,但我认为在某些情况下,在列中存储数组的逗号分隔列表是解决此问题的好方法。

条件包括:

  • 列表不会很长
  • 您无需根据该列表中的值搜索实体

如果一个实体中有多个字符串列表可以创建大量连接,那么这也是一个好主意。

在这些情况下,我会通过为列表提供两个属性来解决它。一个是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]属性,因为无论如何都不会使用此集合,但我认为它使意图更清晰。

答案 2 :(得分:0)

这不起作用。原因是,对于关系数据库,您无法在字段中真正保存数组或集合。由于类中的每个属性都将映射到数据库字段,因此收集的唯一方法是通过一对多关系。所以你需要加入。所以它并不是EF的限制,而是关系数据库的限制。

有些人通过将XML或CSV保存到表格中的字符串字段来解决这个问题。但这被认为是非常糟糕的风格,所以不要这样做。我建议你只需要接受加入。无论如何,它并没有伤害任何人。

答案 3 :(得分:-1)

您尚未正确定义类表。假设你有两个表Foo和FooBar。还有一对多的关系,包括Foo和FooBar。然后,您将定义如下的类。

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列,包括描绘Foo和FooBars之间一对多的FooId