c# - 存储具有多个相同项目的集合

标签 c# sql sql-server entity-framework

我正在使用 EF 将数据存储到 SQL Server 数据库中。

有两种类型的数据:

  1. 图片
  2. 符号

每个符号包含一组图像

public virtual ICollection<Image> Images { get; set; }

并且每个图像都包含一组符号:

public virtual ICollection<Symbol> Symbols { get; set; }

EF 为多对多关系创建关系表。

如果创建(上传)了一个新符号,程序会查看图像表中是否已经上传了这些图像。

如果是,将添加到新符号的图像列表中。

现在有一个包含 3 个图像的符号(都一样!),它将被添加到 Symbols 表中。

但是在关系表中只创建了一个条目!?

所以下次从数据库中读出这个 Symbol 时,它只包含 1 张图像......

我做错了什么?

或者什么才是正确的做法?

表结构:

[Table("Images")]
public class SqlSymbolImgInfo
{
    [Key]
    public int Id { get; set; }

    public String Path { get; set; }
    public long Size { get; set; }
    public String Md5 { get; set; }
    public int X { get; set; }
    public int Y { get; set; }

    public virtual ICollection<SqlSymbol> Symbols { get; set; }

    public override int GetHashCode()
    {
        return System.IO.Path.GetExtension(Path ?? "x.png").GetHashCode() + Size.GetHashCode() + (Md5 ?? "").GetHashCode();
    }
}

[Table("Symbols")]
public class SqlSymbol
{
    [Key]
    public int Id { get; set; }

    public String Description { get; set; }
    public int Type { get; set; }

    public virtual ICollection<SqlSymbolImgInfo> Images { get; set; }
}

enter image description here

创建关系:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();

        modelBuilder.Entity<SqlSymbol>().HasMany(s => s.Images).WithMany(i => i.Symbols);

        base.OnModelCreating(modelBuilder);
    }

添加符号:

  1. 如果图片不存在则添加

  2. 取回添加的图片

  3. 添加符号

    public void AddSymbol(Symbol sym)
    {
        try
        {
            using (var db = new Db())
            {
                // check if images already exists or add them..
                foreach (var img in sym.Images)
                {
                    var exImg = db.FindImage(img);
                    if (exImg == null)
                    {
                        var newImg = db.Images.Add(img.ConvertToSqlSymbolImgInfo());
                        db.SaveChanges();
                        img.Id = newImg.Id; // get Id of new image
                    }
                    else
                    {
                        img.Id = exImg.Id; // get Id of existing image
                    }
                }
    
                var sqlSym = sym.ConvertToSqlSymbol();
                // get the existing entries, otherwise the same image will be added again and again...
                sqlSym.Images = sym.Images.Select(i => db.Images.Find(i.Id)).ToList();
    
                db.Symbols.Add(sqlSym);
                db.SaveChanges();
                sym.Id = sqlSym;
            }
        }
        catch { logIt("error while adding a symbol."); }
    }
    

解释:

我需要为 Entity Framework 使用包装类,因为 SymbolImage 类位于共享库中。 而且我不想在所有其他项目中包含 EF,即使我不在那里使用它也是如此。

一些附加信息:

具有 3 个相同图像的符号:

enter image description here

添加和“搜索”图像后的集合:

enter image description here

将这个Symbol 添加到数据库后,看一下表:

图片表:

enter image description here

和关系表:

enter image description here

!!标记的线应该出现 3 次?!

它是 ID 为 50 的 Symbol,它有 3 个 ID 为 108 的 Images .. 不只是一个!

这是一个简化的项目,只需几行代码即可对其进行测试:

test project

最佳答案

正如您在评论中所写,多对多关系表在两个 FK 键上都定义了 PK,因此不可能将相同的组合放在那里两次。我会首先考虑这种情况在你的商业模式中是否真的可能。如果应该,那么您可以采取的一种方法是手动声明您的中间表并为其提供人工 PK(例如,只是自动递增的 int)。

然后在 EF 中你将有两个一对多关系(从 Symbol 和从 Image 到你可以调用任何东西的中间表 - 比如 ImagesInSymbol 左右)。 使用这些集合会不太方便,但会起作用。作为奖励,您稍后可以在此关系上设置其他属性(如 DateCreatedStatus 等)。

有关更多详细信息,请参阅此 question .

关于c# - 存储具有多个相同项目的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31518070/

相关文章:

sql - 将表达式转换为数据类型 int 以进行基本统计时发生算术溢出错误

c# - 带有 OpenIdDictServer 的 Rich Twitter Digits/Google Auth

c# - 无法将它绑定(bind)到我的网格到 Telerik OpenAccess 数据源

c# - Web API通用错误处理

c# - 隐藏 gridview 行需要两次尝试

mysql - 如何在一个表中按月与另一年的数据进行比较

mysql - 一起使用重复更新低优先级上的插入延迟

sql - 向表中添加数字 id

SQL Server 2005 将变量设置为选择查询的结果

sql - 如何使用SQL Server比较软件版本?