I am trying to create database using Code First approach. When I run the following code I am getting the following exception. Is there anything wrong in the fields that I defined? How can we overcome this?
Exception:
An error occurred while updating the entries. See the inner exception for details.
Inner Exception:
"Invalid object name 'dbo.Dinners'.
Note: I do not have such a table (Dinners) in the database. The code is supposed to create the tables. I just gave connection string to identify the server as mentioned in EF Code First: Cannot connect to SQL Server. Should I change the connection string?
Connections String:
string connectionstring = "Data Source=.;Initial Catalog=LibraryReservationSystem;Integrated Security=True;Connect Timeout=30";
The LibraryReservationSystem database is already existing database. It has no tables. I am expecting EF to create the tables.
The connection string I copied from a working LINQ 2 SQL application. Do I need to make any changes to it to supply to EF?
UPDATE
When I included the following code, the exception got changed. Now it says - "Invalid object name 'dbo.Dinner'.". It is now complaining about Dinner table; not Dinners table.
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
Original CODE
static void Main(string[] args)
{
string connectionstring = "Data Source=.;Initial Catalog=LibraryReservationSystem;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
var product = new Dinner { DinnerID = 1, Title = 101 };
db.Dinners.Add(product);
int recordsAffected = db.SaveChanges();
}
}
using System.Data.Entity;
namespace LijosEF
{
public class Dinner
{
public int DinnerID { get; set; }
public int Title { get; set; }
}
public class RSVP
{
public int RSVPID { get; set; }
public int DinnerID { get; set; }
public virtual Dinner Dinner { get; set; }
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
public DbSet<Dinner> Dinners { get; set; }
public DbSet<RSVP> RSVPs { get; set; }
}
}
REFERENCE
http://nerddinner.codeplex.com/discussions/358197
Entity framework - Invalid Object Name
Invalid object name 'dbo.TableName' when retrieving data from generated table
http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-code-first-walkthrough.aspx
The LibraryReservationSystem database is already existing database. It
has no tables. I am expecting EF to create the tables.
That's not correct. If the database exists EF doesn't create any tables in this database. EF can create the database if it doesn't exist. That is the default database initializer CreateDatabaseIfNotExists that gets applied if you don't change it explicitly. You can select two other initializers: DropCreateDatabaseAlways or DropCreateDatabaseIfModelChanges. But neither of those will only create tables in an existing database but instead delete the database completely and create it from scratch including all tables.
What can you do:
Either delete the database manually (in SSMS for example), then EF will create a new one including the tables
Or use the DropCreateDatabaseAlways initializer once to let EF create the database including the tables, then remove the initializer again
Or if you can't delete the database for whatever reason write SQL code in the Seed method that adds the tables to the database (Wrong, thanks to Mark Stafford's comment)
Or use Code-First Migrations (EF >= 4.3) to add new tables to an existing database when you have added new entities.
#Slauma's answer is the right one - the tables are created upon initialization. It's probably easiest to just delete the database and let EF create it (if you leave your connection string as is, it will create a database called LibraryReservationSystem on the local machine; you should probably specify an explicit host name if you're going to use the connection string in the config at this point).
You would need something along the lines of:
public class NerdDinnersInitializer : DropCreateDatabaseIfModelChanges<NerdDinners> { }
And you would also need to set the initializer in your Main method:
Database.SetInitializer(new NerdDinnersInitializer());
Word to the wise: NEVER deploy an application with an initializer like the one above. You can see this blog post about how to control initializers via the config file for more details on how to control this in production applications.
I've just ran into the exact same issue - I'd already created my database on a development SQL box inside our network that needs SQL authentication.
When I ran my app, no tables were created. I found this awesome but simple article about creating a Code First Database Initializer Strategy which first checks to see if the database exists and then runs a script against the database to create the tables.
As stated in the article - pay attention that when such a strategy is deployed, whenever the application starts over, all the database tables will be recreated! This strategy should only run once.
But you already knew that.
As the error suggests, you do not have a table called Dinners within your database.
Are you using Single or Plural table names? i.e. Dinner or Dinners?
As I understood, you are expecting the code to create DB automatically based on your entities description. But this will not happen unless you create DB explicitly. Please check the following link http://www.simple-talk.com/dotnet/.net-framework/entity-framework-4460---learn-to-create-databases-from-the-model/
and this tutorial on EF codefirst: http://codefirst.codeplex.com/
Once you have your entities designed you can right-click the workspace of the EDMX file and select 'Generate Database from Model...'. Click through until you have a script in your window. For that script you will have to remove DB creation step (if it is there) and go straight for CREATE TABLE ...
Copy-Paste and execute in whatever DB you've got. You might have to adjust the script for a specific RDBMS.
Related
I have an EF Core 6 context that uses temporal tables, and am trying to rename one of the properties on a model.
I have a model that was named PropertyGroupsInvestors, which I renamed to Investment. That worked fine.
I then noticed that the InvestorPayment model had the following...
public int PropertyGroupsInvestorsID { get; set; }
public PropertyGroupsInvestors PropertyGroupsInvestors { get; set; } = new();
...which should also have been renamed. I renamed the two properties as follows...
public int InvestmentsID { get; set; }
public Investment Investment { get; set; } = new();
...and added a migration.
However, when I tried to update the database, it failed with the error "Setting SYSTEM_VERSIONING to ON failed because table 'MyProject.dbo.InvestorPayments' has 10 columns and table 'MyProject.dbo.InvestorPaymentsHistory' has 9 columns."
Looking in SQL Server Management Studio, I can see that both the InvestorPayments and corresponding history tables have both the old PropertyGroupsInvestorsID column and the new InvestmentId column. They both have 10 columns, so I'm not sure what he message means though. See the screenshot...
Any idea how I fix this? Ideally I need to get rid of the PropertyGroupsInvestorsID column from both tables.
Thanks
There is a problem with the renaming of columns in the system versioning table using a code-first approach. So a quick solution (if you don't want to drop temporal tables) can be just to create two migrations. One migration to add a new column, and the second migration to remove the old column.
So first migration will contain both, PropertyGroupsInvestorsID and InvestorsID and then remove PropertyGroupsInvestorsID to create a new migration.
The same problem here like deleting or modifying one field, it looks like when you have a system-versioned table, you can't modify the structure because it's linked to the history table.
Using SQL server doesn't look like there is any problem:
https://learn.microsoft.com/en-us/sql/relational-databases/tables/add-columns-to-a-table-database-engine?view=sql-server-ver15
I have an existing data model Created from a existing MySQL Database. Is it possible to use this model but connect to a identical MsSQL Database?
If I change the connection string and use the metadata from MySql it complains that it can not convert the SqlConnection to a MySqlConnection (of course).
How is this properly done? Is it possible at all?
I think Miguel led me to a solution:
Solution 1
In my case I had a separate project in my solution which keeps the data model. In that project I added another ADO.NET Entity Data Model generated from the MS SQL DB. At this point it would already work, besides that we would have to change the code wherever we create or access the context. To solve this I've created a interface for the context object that the EF Wizard generated, and implemented it in a partial type. This way I can "Update the Model from Database" without loosing it:
public partial class EntitiesMs : DbContext
{
public EntitiesMs()
: base("name=EntitiesMs")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
// Your DbSet<...> Stuff
}
public partial class Entities : DbContext
{
public Entities()
: base("name=Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
// Your DbSet<...> Stuff
}
And in separate files of course:
public partial class Entities : IDbEntities
{
}
public partial class EntitiesMs : IDbEntities
{
}
A Factory could then return the desired object. Although this has some downsides:
If a new table is created in the DB the interface has to be modified
You would have to cast the object from the factory to access
methods like SaveChanges() (methods from the base type)
And maybe some others I have overlooked.
Solution 2
Another "quick and dirty" way I've found is to add another project to the solution and add the MS Data Model there. Make sure that the Model has the exact same name as the one for MySQL. Then the only things you have to do in your startup project is, switch the reference to the other project and switch the connection strings.
The only problem that you need to solve if the EDMX file. You may need to have one to the MySQL and one distinct to the MSSQL and specify which one you want at the connection string level.
An EF data model connection string looks like this:
<add name="Entities" connectionString="metadata=res://*/CMBS.csdl|res://*/CMBS.ssdl|res://*/CMBS.msl;provider=System.Data.SqlClient;provider connection string="data source={database};initial catalog=;persist security info=True;user id=;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
You need to update the metadata part of the connection string. Here you can find more information to manipulate EDMX files.
Hope this help!
I am developing a data intensive app in C# and need some advice on the best method to manage my data. My application will use a number of related tables with a lot of movement backwards and forwards between the app and the database.
My question is, what method would be best to handle data? All of my data fields are controlled within their own classes and collections, so hence, the question is really more of a case of what is the best method to bind my collections and objects to the database.
Should I manually create my own SQL connections / SQL Insert / Update queries, or is there another way to do this? For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Many thanks
Q. For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Entity Framework sounds like something you're looking for. There is, of course, some setup involved. With most web projects, Entity Framework is automatically added, and if not you can always add it via NuGet package manager.
EntityFramework binds your models to a Database through the DbContext object, and Code First will even generate a database if one does not exist based on your models (if one does exist and the models change, you might have to migrate: More reading). I will be taking that approach (you can later change the following code to a connection string to a live DB).
First, you need to tell your application what database to use (whether it exists or not), and this can be done in the Web.Config file (not the only approach).
Web.Config
<configuration>
....
<connectionStrings>
<add name="ConnectionStringName" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf;Initial Catalog=DATABASENAME;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
NOTE - this connection string will only work in VS2015. For previous versions, use:
Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf
More reading on configuring Entity Framework
Now, we can use "ConnectionStringName" to connect our context.
The Context class will have to inherit from the DbContext object, and we will pass this connection string name to the base constructor (DbContext exists in the System.Data.Entity namespace). I will use two generic models that look identical (ModelA ModelB) --
ModelA and ModelB
using System.ComponentModels.DataAnnotations;
public class ModelA
{
public int Id { get; set; }
[Required(ErrorMessage="You need to enter a name!")]
[StringLength(40)]
public string Name { get; set; }
}
NOTE - I'm using DataAnnotations (Required, StringLength) - these are really cool and can be very useful when implementing CRUD operations on your model.
ALSO -- Entity Framework will automatically make properties that are named: Id (or any case form) or ModelNameId the primary key. There are ways to override this.
More reading on DataAnnotations
You can even create your models with relationships in mind. If ModelA will have a one-to-many relationship with ModelB, you can reflect this relationship in code:
public virtual ICollection<ModelB> ModelBs {get; set;}
More reading on creating relationships
We will now map your models to tables using the DbSet collection. Here's how that looks:
using System.Data.Entity;
using YourProject.Data.Models;
namespace YourProject.Data.DAL
{
public class YourContext : DbContext
{
public YourContext() : base("ConnectionStringName")
{
}
public DbSet<ModelA> ModelAs { get; set; }
public DbSet<ModelB> ModelBs { get; set; }
}
}
Database Initialization Strategies - for seeding your database with data on creation.
More reading on configuring the context
I will never be able to detail everything you can do - but here are a few short examples:
Q. What does all this do?
You now have a strongly-typed object connected to your database. It's as simple as creating a new Context object:
YourContext yourContext = new YourContext();
Retrieving a whole table is as easy as:
IEnumerable<ModelA> modelAs = yourContext.ModelAs;
or finding a row by Id
ModelB modelB = yourContext.ModelBs.Find(id);
Say you grabbed modelB and want to update it. It's as easy as:
modelB.Name = "Here's the new name";
yourContext.Entry(modelB).State = EntityState.Modified;
yourContext.SaveChanges();
Adding:
yourContext.ModelAs.Add(newModel);
Removing:
yourContext.ModelBs.Remove(modelB);
REMEMBER Add/Update/Delete methods will ALL require a call to SaveChanges(); from the Context. Otherwise they will be discarded.
Of course, this is probably the most basic rundown of Entity Framework available. To see more of it in action check out these tutorials:
WebForms with Entity Framework - Wingtip Toys
MVC with Entity Framework - Contoso University
Hope this may be of assistance for someone.
I ran into what I think is a really odd situation with entity framework. Basically, if I update an row directly with a sql command, when I retrive that row through linq it doesn't have the updated information. Please see the below example for more information.
First I created a simple DB table
CREATE TABLE dbo.Foo (
Id int NOT NULL PRIMARY KEY IDENTITY(1,1),
Name varchar(50) NULL
)
Then I created a console application to add an object to the DB, update it with a sql command and then retrieve the object that was just created. Here it is:
public class FooContext : DbContext
{
public FooContext() : base("FooConnectionString")
{
}
public IDbSet<Foo> Foo { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().ToTable("Foo");
base.OnModelCreating(modelBuilder);
}
}
public class Foo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//setup the context
var context = new FooContext();
//add the row
var foo = new Foo()
{
Name = "Before"
};
context.Foo.Add(foo);
context.SaveChanges();
//update the name
context.Database.ExecuteSqlCommand("UPDATE Foo Set Name = 'After' WHERE Id = " + foo.Id);
//get the new foo
var newFoo = context.Foo.FirstOrDefault(x => x.Id == foo.Id);
//I would expect the name to be 'After' but it is 'Before'
Console.WriteLine(string.Format("The new name is: {0}", newFoo.Name));
Console.ReadLine();
}
}
The write line at the bottom prints out "Before" however I would expect that it prints out "After". The odd thing about it is that if I run profiler I see the sql query run and if I run the query in management studio myself, it returns "After" as the name. I am running sql server 2014.
Can someone please help me understand what is going on here?
UPDATE:
It is going to the database on the FirstOrDefault line. Please see the attached screen shot from sql profiler.
So my question really is this:
1) If it is caching, shouldn't it not be going to the DB? Is this a bug in EF?
2) If it is going to the db and spending the resources, shouldn't EF update the object.
FooContext includes change tracking and caching, so the in-memory object that is returned from your query is the same instance that you added earlier. Calling SaveChanges() does clear the context and FooContext is not aware of the changes that happened underneath it in the database.
This is usually a good thing -- not making expensive database calls for every operation.
In your sample, try making the same query from a new FooContext, and you should see "After".
update
Responding to your updated question, yes, you are right. I missed before that you were using FirstOrDefault(). If you were using context.Find(foo.Id), as I wrongly assumed, then there would be no query.
As for why the in-memory object is not updated to reflect the change in the database, I'd need to do some research to do anything more than speculate. That said, here is my speculation:
An instance of the database context cannot return more than one instance of the same entity. Within a unit of work, we must be able to rely on the context to return the same instance of the entity. Otherwise, we might query by different criteria and get 3 objects representing the same conceptual entity. At that point, how can the context deal with changes to any of them? What if the name is changed to a different value on two of them and then SaveChanges() is called -- what should happen?
Given then that the context tracks at most a single instance of each entity, why can't EF just update that entity at the point at which a query is executed? EF could even discard that change if there is a pending in-memory change, since it knows about those changes.
I think one part of the answer is that diffing all the columns on large entities and in large result sets is performance prohibitive.
I think a bigger part of the answer is that it executing a simple SELECT statement should not have the potential to cause side effects throughout the system. Entities may be grouped or looped over by the value of some property and to change the value of that property at an indeterminate time and as a result of a SELECT query is highly unsound.
I am getting the exception above when I run an application. The application is using asp.net mvc 3 / C#. I made an mdf file and added it under App_Data folder in Visual Web Developer Express. I added connection strings to the web.config folder but when I run and browse to /store, I get the error above with the line var categories = storeDB.Categories.ToList(); highlighted. My database contains 6 tables and one of them is Category.
Controller:
EventCalendarEntities storeDB = new EventCalendarEntities();
public ActionResult Index()
{
var categories = storeDB.Category.ToList();
return View(categories);
}
Connection strings in web.config file:
<connectionStrings>
<add name="EventCalendarEntities"
connectionString="data source=.\SQLEXPRESS;
Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|\MvcEventCalendar.mdf;
User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
This usually means a simple configuration issue:
perhaps there genuinely is no such table
perhaps the table is there, but there is no dbo scheme (it might be in Fred.Categories)
perhaps the db is case-sensitive (which is fine), and the table is actually dbo.CATEGORIES
Any of these will cause the above exception. In particular, you state:
My database contains 6 tables and one of them is Category.
Now to a machine, Category != Categories
Try using model builder class. It is the way to configure or explicitly define the mapping between table and model class.
In your entity/context class try adding this code
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Category>().ToTable("Category");
}
It's a method. Make sure you are using all the including statements.
Since this was still top search hit on the exception in April of 2018 and it led me to a solution, let me tack this on for a specific situation...
Our application is based on ABP and ABP.Zero, and we already have a pattern that fit Marc's answer. While I bet explicit mapping in the OnModelCreating method (a la Dhananjay's answer) would have worked perfectly, it seemed like ABP's mapping was working perfectly up to this point and I didn't want to break the pattern.
My solution was to add a table attribute to the entity class, and this settled EF's confusion.
using System;
using Abp.Domain.Entities;
using System.ComponentModel.DataAnnotations.Schema;
namespace Discovery.History
{
[Table("HistoryRecords")]
public class HistoryRecord : Entity<int>
{
public int ResearcherCount { get; set; }
public DateTime DateSubmitted { get; set; }
public string Comments { get; set; }
}
}
What you really want to do to fix this is in you Context class you should have a method called OnModelCreating... make sure it has this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
Proven,tested & verified for table with name category or any SQL keywords named table use ToTable to instruct specific table name
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<category>().ToTable("category");
}
If you have a Class for mapping properties and keys without this.Map.(a table in db necessary to mapping), EntityFramework expect you have one table named like Category but convert in plural, so "Categories".. To resolve you can add this.Map(in correct table existing in your DB).
in your DbContext where you create DbSet change Categories to Category
I resolved same issue by this way