保存列表对象的SQLite实体框架核心问题

fgw7neuy  于 2022-11-15  发布在  SQLite
关注(0)|答案(1)|浏览(156)

我是实体框架的新手,我只是在探索这项技术和SQLite,以便在一个新项目中使用。
在尝试使用一些伪数据初始化我的数据库时,我遇到了一个问题。
以下是我的模型课:

public class Format
{
    [Key]
    public int FormatId { get; set; }

    public string FormatName { get; set; }

    public string FormatType { get; set; }

    public string ValueType { get; set; }

    public List<Value> InValue { get; set; } = new List<Value> { };

    public List<Value> OutValue { get; set; } = new List<Value> { };
}

public class Value
{
    [Key]
    public int ValueId { get; set; }
    public string ValueName { get; set; }
}

以下是我的数据库上下文:

public class MyDbContext : DbContext
{
    public DbSet<Format> Formats { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Filename=MyDatabase.db", options =>
        {
            options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
        });

        base.OnConfiguring(optionsBuilder);
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Format>().ToTable("Formats", "test");
        modelBuilder.Entity<Format>(entity =>
        {
            entity.HasKey(e => e.FormatId);
            entity.HasMany(e => e.InValue);
            entity.HasMany(e => e.OutValue);
        });

        base.OnModelCreating(modelBuilder);
    }
}

下面是我的初始化代码:

public static void InitializeDatabase()
    {
        string dbName = "MyDatabase.db";
        if (File.Exists(dbName))
        {
            File.Delete(dbName);
        }
        using (var dbContext = new MyDbContext())
        {
            //Ensure database is created
            dbContext.Database.EnsureCreated();
           

            if (!dbContext.Formats.Any())
            {
                dbContext.Formats.AddRange(new Format[]
                {
                    new Format
                    { 
                        FormatId=1, 
                        FormatName = "tm", 
                        FormatType = "VALUE", 
                        ValueType = "num", 
                        InValue = new List<Value> { new Value { ValueId = 1, ValueName = "0" }, new Value { ValueId = 2, ValueName = "1" }, new Value { ValueId = 3, ValueName = "2" } }, 
                        OutValue = new List<Value> { new Value { ValueId = 1, ValueName = "0h" }, new Value { ValueId = 2, ValueName = "1h" }, new Value { ValueId = 3, ValueName = "2h" } } 
                    },
                });
                dbContext.SaveChanges(); // crashes here
            }
        }
    }

我得到以下错误:
System.InvalidOperationException:‘无法跟踪实体类型’Value‘的示例,因为已在跟踪具有与{’ValueId‘}相同键值的另一个示例。附加现有实体时,请确保只附加了一个具有给定键值的实体示例
当我在InValue和OutValue列表中有多个项目时,它会崩溃。你可以看到我在每个单子上都有3个项目。如果我在每个列表中都有一项,那么就不会有错误。我想我在创建模型时可能遗漏了一些东西,但现在我确定了什么。

rkue9o1l

rkue9o1l1#

要引用一个表两次,您必须提供外来ID。在您的情况下,实体之间没有关系。

public class Format
{
    [Key]
    public int FormatId { get; set; }

    public string FormatName { get; set; }

    public string FormatType { get; set; }

    public string ValueType { get; set; }

    public List<Value> InValue { get; set; } = new List<Value> { };

    public List<Value> OutValue { get; set; } = new List<Value> { };
}

public class Value
{
    [Key]
    public int ValueId { get; set; }
    public string ValueName { get; set; }

    public int InFormatId { get; set;}
    public int OutFormatId { get; set;}

    public virtual Format InFormat { get; set; }
    public virtual Format OutFormat { get; set; }

}

流畅接口:

modelBuilder.Entity<Value>()
               .HasOne(m => m.InFormat)
               .WithMany(t => t.InValue)
               .HasForeignKey(m => m.InFormatId)
               .OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Value>()
               .HasOne(m => m.OutFormat)
               .WithMany(t => t.OutValue)
               .HasForeignKey(m => m.OutFormatId);
               .OnDelete(DeleteBehavior.Cascade);

并且您应该将值表添加到DbContext

public class MyDbContext : DbContext
{
    public DbSet<Format> Formats { get; set; }

    public DbSet<Value> Values { get; set; }
    ///....
}

相关问题