【问题标题】:C# EntityFramework Core - Invalid object name, cannot update databaseC# EntityFramework Core - 对象名称无效,无法更新数据库
【发布时间】:2017-02-20 18:04:05
【问题描述】:
  1. 将 MDF 数据库添加到名为 FxTrader.mdf 的项目中
  2. 创建简单模型:

    public class MarketTickContext : DbContext
    
    {
    
    
    public DbSet<MarketTickRecord> Records { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string connectionString = @"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = ""C:\Users\asmodat\Documents\Visual Studio 2015\Projects\Asmodat FxTrader\Asmodat FxTrader Data\FxTrader.mdf""; Integrated Security = True";
        optionsBuilder.UseSqlServer(connectionString);
    
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MarketTickRecord>()
            .HasKey(mtr => new { mtr.Company, mtr.Symbol });
    
        modelBuilder.Entity<MarketTickRecord>()
            .HasMany(mtr => mtr.Ticks);
    
        modelBuilder.Entity<MarketTick>()
            .HasKey(mt => mt.Time);
    }
    }
    
  3. 在控制台中运行:Add-Migration MarketTickMigration.v3 -> 成功

  4. 然后更新数据库 -> 成功

但首先。此操作后的数据库看起来不像我预期的那样。 我认为应该有 2 个表:MarketTickRecord 和 MarketTick 表

But only some wierd table appears, that looks like this.

所以当我运行这段代码时:

_context = new MarketTickContext();
_context.Records.Add(new MarketTickRecord());
_context.SaveChanges();

最后一行产生异常:

An unhandled exception of type 'Microsoft.EntityFrameworkCore.DbUpdateException' occurred in Microsoft.EntityFrameworkCore.dll

Additional information: An error occurred while updating the entries. See the inner exception for details.

{"Invalid object name 'Records'."}

如果我尝试也一样:

_context.Records.Count()

谁能指出我做错了什么? 如何更新我的数据库以使其正常工作?

编辑##############################-> 进度

我正在慢慢弄清楚发生了什么,所以我创建了一个最简单的模型来逐步检查问题所在。

public class TestContext : DbContext
    {
        public DbSet<TestRecord> Tests { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Asmodat_FxTrader_Data.MarketTicksDb.v14;Trusted_Connection=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TestRecord>()
                .HasKey(c => new { c.SomeK1, c.SomeK2 });
        }
    }

以上模型运行良好。因此,在创建新的“测试”类后会出现问题,该类将放置在 TestRecord 类的列表中,例如:

 public class TestRecord
    {

        public string SomeK1 { get; set; }

        public string SomeK2 { get; set; }

        public List<Test> Tests { get; set; }
    }

public class Test
    {

        public long SomeK1 { get; set; }

        public int V1 { get; set; }

        public int V2 { get; set; }
    }

如果我现在将 OnModelCreating 更新为:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TestRecord>()
                .HasKey(c => new { c.SomeK1, c.SomeK2 });

            modelBuilder.Entity<Test>()
                .HasKey(c => c.SomeK1);
        }

出现与原始问题相同的异常......

所以问题出在此处,与此 List 对象或 OnModelCreating 中缺少的某些内容有关。有什么想法吗?

编辑#########################################

按照 cmets 中的建议,我也试过这个:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            var tr = modelBuilder.Entity<TestRecord>();
                tr.HasKey(c => new { c.SomeK1, c.SomeK2 });
                tr.HasMany(c => c.Tests);
                tr.ToTable("Records");

            var t = modelBuilder.Entity<Test>();
                t.HasKey(c => c.SomeK1);
                t.ToTable("Tests");
        }

仍然存在相同的问题,仅在绑定执行时出现错误更改中的名称

TestContext con = new TestContext();
            con.Tests.Add(new TestRecord() { SomeK1 = "a1", SomeK2 = "a2", Tests = new List<Test>() });
            con.SaveChanges();

编辑#########################################

我需要的是有许多 TestRecord,其中可以有许多 Test 存储在列表中(一对多)。

但是还需要的是,假设 TestRecord with SomeK = {'a','b'} 和 TestRecord with SomeK = {'c', 'd'},可能有具有相同 id 的 Test ,但是是不同的对象(例如不同的 V1 和 V2)。

例如(伪代码):

TestRecord['a','b'].Tests[1].v1 == 1
TestRecord['c','d'].Tests[1].v1 == 2

有可能吗?有谁知道如何使用 ef core flex API 实现这一目标?因为我所有的尝试都失败了。

【问题讨论】:

  • 迁移CS文件的内容是什么? Up() 方法中有什么东西吗?
  • @jao 是的,它们是,充满了代码,对我来说没什么可疑的:Up(MigrationBuilder migrationBuilder) ... migrationBuilder.CreateTable( ... 等等
  • 我注意到的一件事是数据库创建的顺序可能是错误的 - 自定义迁移文件的 Designer.cs 版本包含日期,在我的情况下,我的自定义迁移的日期正在运行在 dotnet ef 生成的那个之前,因此没有找到对象。

标签: c# mysql entity-framework


【解决方案1】:

我目前正在一个学校项目中使用实体框架,并且我已经发生了相当多的奇怪事情,所以我感受到了你的痛苦。我不确定您的课程对于 MarketTickRecord 或 MarketTick 到底是什么样的,但我的教授让我们添加到我们的数据库对象中的一件事是数据注释 [Table("YOUR_TABLE_NAME)"] 上面的“public class ...”行和上面的 [Key]类中将用作主键的属性。此外,我们使用 Visual Studio 中的数据库设计器手动创建了表。不确定这是否对您有帮助,但值得一试!

【讨论】:

  • 如果我删除整个 OnModelCreating,并且只添加一个 ID + 添加标签,如 [Key]、[Require] 以及您上面建议的内容,则错误变为:附加信息:无效的对象名称“MarketTickRecord”。
  • 我注意到在 AttachDBFileName 之后的连接字符串中,有两组引号“值”。尝试摆脱其中一个,看看是否可以解决问题。也摆脱了那里的一些额外间距。试试看:"Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename="C:\Users\asmodat\Documents\Visual Studio 2015\Projects\Asmodat FxTrader\Asmodat FxTrader Data\FxTrader.mdf";Integrated Security=true";
  • 也看看这个link。它引用了您遇到的错误,并告诉您为什么/如何可能修复它
【解决方案2】:

为后代解决,不要使用现有的数据库 - 它必须由 ef core 自己从头开始创建,否则它会在保存等时抛出异常。

public class TestContext : DbContext
    {
        public DbSet<Test> Tests { get; set; }
        public DbSet<TestRecord> TestRecords { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string connectionString = @"Server=(localdb)\mssqllocaldb;Database=Asmodat_FxTrader_Data.TestDb.v1;Trusted_Connection=True;";
            optionsBuilder.UseSqlServer(connectionString);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            var tr = modelBuilder.Entity<TestRecord>();
            tr.HasMany(p => p.Tests).WithOne(x => x.TestRecord).HasForeignKey(p => p.TestRecordId);
        }
    }

    [Table("TestRecords")]
    public class TestRecord
    {
        public TestRecord()
        {
            this.Tests = new List<Test>();
        }

        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int TestRecordId { get; set; }

        public string SomeK1 { get; set; }

        public string SomeK2 { get; set; }

        public virtual ICollection<Test> Tests { get; set; }
    }

    [Table("Tests")]
    public class Test
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int TestId { get; set; }

        public int TestRecordId { get; set; }

        public virtual TestRecord TestRecord { get; set; }


        public long VT { get; set; }

        public int V1 { get; set; }

        public int V2 { get; set; }
    }

【讨论】:

  • -1 这不是真的。 EF Core 支持使用 db first 和 code first 策略。我自己正在做一个项目,我正在使用一个包含 170 多个表的遗留数据库,并且到目前为止它已经映射了大约 35 个表。
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 2013-11-25
相关资源
最近更新 更多