实体框架将集合属性映射到一列

时间:2017-04-24 10:03:42

标签: c# entity-framework

我有模特:

 public class FlyerPage
{
    public Guid Id { get; set; }
    public string Picture { get; set; }
    public int? Page { get; set; }

    public string Text { get; set; }

    public ICollection<string> Keywords { get; set; }

    public Guid FlyerId { get; set; }

    public virtual Flyer Flyer { get; set; }
}

我想将Keywords映射到FlyerPage表格中的一列。 我认为最好的方法是将它分成由逗号分隔的值,如

"one", "two", "three". 

怎么做? 通过FluentAPI。

编辑 - 到另一个表

The type 'ICollection<string>' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 


 modelBuilder.Entity<FlyerPage>().Map(m =>
        {
            m.Property(p => p.Keywords);
            m.ToTable("Keyword", "Flyers.Page");
        });

编辑2:确定这项工作

        modelBuilder.Entity<FlyerPage>().Map(m =>
        {
            m.Properties(p => p.Keywords);
            m.ToTable("FlyerPageKeywords");
        });

但是如何将它连接到很多?

4 个答案:

答案 0 :(得分:2)

根据您的目的(例如,如果您想按关键字搜索),您可以创建两个新表,一个用于Keyword s(其中每个记录都是关键字),另一个用于映射关系一个FlyerPage和一个Keyword,其中包含FlyerPageKeyword的ID作为外键。

通过关键字搜索可能会更有效率(即使使用所有JOIN),这样,您可以避免存储重复值,并且很可能更接近应用程序的逻辑。

您将最终得到两个表(还有一个表将自动生成):

public class FlyerPage
{
    public Guid Id { get; set; }
    public string Picture { get; set; }
    public int? Page { get; set; }

    public string Text { get; set; }

    public ICollection<Keyword> Keywords { get; set; }

    public Guid FlyerId { get; set; }

    public virtual Flyer Flyer { get; set; }
}

public class Keyword
{
    public Guid Id { get; set; }
    public string Value { get; set; }

    public virtual ICollection<FlyerPage> FlyerPages { get; set; }
}

然后使用FluentAPI进行多对多映射:

modelBuilder.Entity<FlyerPage>() 
    .HasMany(t => t.Keywords) 
    .WithMany(t => t.FlyerPages) 
    .Map(m => 
    { 
        m.ToTable("FlyerPageKeywords"); 
        m.MapLeftKey("FlyerPageID"); 
        m.MapRightKey("KeywordID"); 
    });

我认为它会解决你的问题。我不是在FluentAPI中完全“流利”,你可能必须将类的构造函数中的集合初始化为空集合。

此外,根据documentation,根据Plunkr,将关系设置为双向(即在ICollection<FlyerPage>对象中存储Keyword)的原因是:

  

按照惯例,Code First总是将单向关系解释为一对多。

答案 1 :(得分:2)

如果我理解你的要求正确,你想做一个糟糕的数据库练习,将逗号分隔的争论添加到记录的一列。 我不明白你想要以指定的方式完成什么。 无论如何要实现你的要求。

//这真是一个不好的做法。我强烈建议您选择SándorMátyásMárton的解决方案,这是实现您的实际用例的最佳实践。

您需要使用不同的实体

 public class FlyerPage
{
    public Guid Id { get; set; }
    public string Picture { get; set; }
    public int? Page { get; set; }

    public string Text { get; set; }

    public string KeywordsCollection { get; set; }

    public Guid FlyerId { get; set; }

    public virtual Flyer Flyer { get; set; }
}

您可以在这里设置

KeywordsCollection = string.Join(",", flierPage.Keywords); 
//flierPage is the viewmodel object and flierPage.Keywords is the collection 

//you got from the viewmodel

答案 2 :(得分:0)

如果你真的必须将规范化数据存储在一个字段中,那么你可以通过修改你的类来实现这一点:

public class FlyerPage
{
    public ICollection<string> Keywords
    {
        get
        {
            return _keywords.Split(',');
        }
        set
        {
            _keywords = string.Join(",", value);
        }
    }

    private string _keywords;
}

然后在您的流畅映射中,将Keywords属性设置为忽略并映射_keywords字段。

答案 3 :(得分:0)

创建关联关键字列表。

public class FlyerPage
    {
        .....

        public string JoinedKeywords 
        {
           get
           {
              return String.Join(",", this.Keywords);
           }
        }
        public ICollection<string> Keywords {get; set;}
    }