简体   繁体   中英

C# EntityFramework Core - Invalid object name, cannot update database

  1. Added MDF database to project called FxTrader.mdf
  2. Created simple Model:

     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. Run in console: Add-Migration MarketTickMigration.v3 -> success

  4. Then Update-Database -> success

But first. Database after this operation does not look like I expected. There should be 2 tables in my opinion: MarketTickRecord and MarketTick table

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

So when I run this code:

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

The last line generates exception:

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'."}

same goes if I try:

_context.Records.Count()

Can anybody point me to direction what am I doing wrong ? How can I update my database so it works ?

EDIT ############################### -> Progress

I am slowly figuring out what is going on, so I created the simplest possible model to step by step check what is wrong.

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

Above model is working great. So problem appears after creating new 'Test' class that will be placed inside list in TestRecord class, for example:

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

If I now update OnModelCreating to this:

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

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

The same exception appears as in original question....

So problem, is somewhere here, and has to do with this List object or something missing in OnModelCreating. Any ideas ?

Edit ##########################################

I also tried this, as suggested in the comments:

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

still the same problem remains only name inside error changes while tying to execute

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

Edit ##########################################

What I need is to have Many TestRecord's that can have many Test's inside them stored in list (One to Many).

But what is also required is that, lets say TestRecord with SomeK = {'a','b'}, and TestRecord with SomeK = {'c', 'd'}, might have Test's that have the same id, but are a different object (for example different V1 and V2).

For example (pseudocode):

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

Is it possible ? does anyone knows how to achieve this with ef core flex API ? Because all my tries are failing.

I am currently using the entity framework in a school project and Ive had my fair share of weird things happen so I feel your pain. I'm not sure what exactly your class looks like for MarketTickRecord or MarketTick, but one thing my professor had us add to our database objects were the data annotations [Table("YOUR_TABLE_NAME)"] above the 'public class ...' line and [Key] above the property in the class that would serve as the primary key. Also, we manually created our tables using the database designer in visual studio. Not sure if this will help you or not, but its worth a try!

Solution for future generations, don't use existing database - it must be created from scratch by ef core itself otherwise it will throw exceptions on save etc.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM