Access a table of a separate database using entity framework - asp.net-mvc

I have an MVC website with its own database and everything is working fine. Now I want to access a table of a database from a different MVC site. I added the connection string in the Web.config and named it OldMvcDB. Then I added a class to access this table:
public class OldSiteDB : DbContext
{
public OldSiteDB() : base("name=OldMvcDB") { }
public DbSet<OldTable> OldTables { get; set; }
}
When I try to access this table, I get the error:
The model backing the 'OldSiteDB' context has changed since the database was created.
This is because the old database has a lot of other tables so the context doesn't match.
How can I access this one table without having to duplicate all the items in my new site?

You should add the following to your class constructor:
Database.SetInitializer<OldSiteDB>(null);
From this SO answer.

Related

Set a Primary Key for an Entity without ingaffect database

I'm working on an ASP.NET MVC project, I use Entity Framework (Database First), I created a data model depend on SQL server database, I created a Table in the database and I updated the data model from the database, and when I try to add a record to the new table I created (this table doesn't have a PK) I got an error, when I search about the error I Understood that in Entity Framework need to have a PK for Entity.
So I ASK if I can set a Primary Key for an Entity without affect database, or any other solution to solve this problem.
You can use partial Class for set Key and without effect Original Model and Database
// orginal class **Entity** `YourEntity.cs`
public class YourEntity
{
public int Id { get; set; }
}
Then create a new Class must name different ordinal class ex YourEntityMeta.cs it is physical name
// must change name ordinal class `YourEntity.cs` but add **partial** keyword
[MetadataType(typeof(Metadata))]
public partial class YourEntity
{
sealed class Metadata
{
[Key]
public int Id { get; set; }
}
}
Entity Framework always needs a primary key column with name id. Add a column (id) in the database table and set "Is Identity: true" for it. Then update the database model of your project.

Why is my custom DbContext creating a table on insert?

I'm working on an ASP MVC project.
Here are the steps I followed :
I added entity framework in my project references
I connected to my SQL SERVER database and then copied the associated connection string in Web.config using this answer. The connection is successful
I created manually my own DbContex class. Below is its code :
public class MyConxtext : DbContext
{
public MyConxtext() : base("name = MyConnString"){}
public DbSet<user> user { get; set; }
}
Now user here not only is the name of my table user in SQL server but also is the name of my model user in my ASP MVC.
My problem is that :
- when I wanted to persist (several item in a session) via MyContext.SaveChanges(), it has created another table in my database named users ... Notice the plural here users... So instead of working on the table user, it created another table called users and persited data on that table.
My context also is not able to read data from the user table. BUT as I said it processes everything is the schema of the connection string
How can I solve that problem ?
Not only that it has also created another table in my schema called MigrationHistory which contain data about my project...
You can override OnModelCreating method in your DbContext and add the following line
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
This should remove pluralization for naming
Entity Framework by default pluralizes the table name when it generates it from the supplied entities.That means, if there is a class named Student as entity object and you declare a DbSet <Student> on your context (class inherited from DbContext), by default EF creates the table in a plural form of the entity name. This is a general concept as the table will contain several rows of that entity type, which refers it will be a collection of the entities, in our case it will make a table named Students.
If you want to remove this default convention (System.Data.Entity.ModelConfiguration.Conventions), you can override the method named
onModelCreating()
of DbContext class.
In your code you can do
public class MyConxtext : DbContext
{
public MyConxtext() : base("name = MyConnString"){}
public DbSet<user> user { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove < PluralizingTableNameConvention > ();
}
}
This will stop pluralizing the table's name in your database and it will use the user table of your database as you mentioned.

MVC4 Multiple Databases

I'm new to MVC4 framework & been working on an Licensing application that must use different databases for different products (each database contains handful tables for one product - all generated by proprietary licensing tool). My application shall be able to support CRUD functions on various products, thus requiring more than one DbContext objects in relation to different model for each product.
As far as I know, each such DbContext object requires a connection string in the Web.config file. I'm struggling to list (Index.cshtml) existing licences for various products, using DropDownList control, as for each product I'd need to connect to a different database whenever the user choose a different product from the DropDownList control.
Any help will be highly appreciated. Thanks.
As I understand your question, the core issue is you are struggling to connect to a different db, whenever user selects a different product from a DropDownList. As you said, yes DbContext object requires a connection string in the Web.config file. You can specify multiple connection strings in a config.
Also you can definitely pass different connection strings to DBContext constructor. Typically your DAL/Data Access Layer or Repository layer would pull appropriate connection string from the Web.Config/App.config and pass it to the DBContext constructor. See a similar approach here and here.
UPDATE :
You cannot share the same DbContext with multiple databases. You need multiple DbContexts for each of your DB.
Additional
There are few of doing this, but if you use Repostory and Unit Of Work pattern, you can use an approach like this
Each DbContext you going to have, you can associate with set of entities within that database in context. Something like below
public class ProductContext : DbContext
{
public ProductContext ()
: base("connectionStringA")
{
}
public DbSet<Product> Accounts { get; set; }
}
public class LicenceContext : DbContext
{
public LicenceContext ()
: base("connectionStringB")
{
}
public DbSet<Licence> Licenses{ get; set; }
}

Modeling an existing database

I want to generate a model based on an existing database -- I thought it would be as simple as writing the model, adding a DbContext class, and configuring a connection string:
namespace MyProject.Models
{
public class Account
{
public int Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
}
public class AccountDBContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
}
}
With a simple boilerplate controller
public ActionResult Index()
{
return View(db.Accounts.ToList());
}
The boilerplate view, which I won't post here, which lists all of the members of the db object that we return.
ANd finally, a connection string:
<add name="AccountDBContext" providerName="System.Data.SqlClient" connectionString="[server connection string]" />
Only problem is I don't see any entries being displayed. It's definitely connecting, but not retrieving or displaying the data that the particular DB contains.. am I missing something?
Edit
Ok, so first thing is first: it wasn't connecting. I had a typo in my connection string name. It was hitting the default, and subsequently displaying nothing.
What I am getting now, though, is The model backing the 'AccountDBContext' context has changed since the database was created.
Is this because my model doesn't match exactly to what the database contains?
This is the "Code First with an Existing Database" scenario.
What version of EF are you using?
In EF 4.3 when you let code first create a database for you, it inserts a Migration-History table into the new database. It’s hidden in System Tables.This is equivalent to the EdmMetadata table you got with EF 4.1 & 4.2. But when you already have the database you can use code first migrations. (http://msdn.microsoft.com/en-US/data/jj591621)
Either way you should probably check if such a table exist. If it does you can delete it and then you'll be solely responsible to correctly matching your pocos to the database.
Another quick workaround i have found is putting
Database.SetInitializer<YourContext>(null);
to your Application_Start() in Global.asax
See also this similar question: Entity Framework Code Only error: the model backing the context has changed since the database was created

Entity framework 4 code first, use the same model to multiple tables?

Im using Entity Framework 4 with code first. I have a model and i want to be able to map this model to a different table in the database based on a configuration file.
Example model:
public class Statistic
{
[Key]
public int id { get; set; }
public string jobName { get; set; }
public DateTime date { get; set; }
public int pages { get; set; }
}
Each customer has a configuration file where the table name that should be used is specified. So each customer should then have its own table (in the same database) with the model above.
How can i do this with Entity Framework 4?
I tried this in my DbContext:
modelBuilder.Entity<Statistic>().ToTable(tabelName);
But what EF does when i use this is to change the existing table name to the new tableName, not creating and using a new one.
Thanks!
It is not possible. Each class can be mapped only once per mapping set (per context in common cases). Why? Because the access point to database is a DbSet (or ObjectSet in ObjectContext API) and it is simply created this way:
var set = dbContext.Set<Statistics>();
How should EF know which mapping of Statistics class should be used? It must know which mapping to use to query correct table and to save changes to correct table. You can probably argue that it could be defined as parameter but that would expose mapping details outside to upper layer - that is undesirable.
Edit:
If your application logic never needs access to more than one customer's statistics you can create mapping per customer dynamically. You need:
Create instance of DbModelBuilder and define mapping (or fill Configurations) - in this step you will provide the name of the table for current customer
Call Build method to get DbModel instance
Call Compile on DbModel instance to get DbCompiledModel instance
Cache compiled model somewhere. Model compilation is expensive operation and you need to do it only once per each customer (and per each application restart).
Pass compiled model to DbContext constructor and use that context instance to access data only for that customer
If you need to simultaneously access data for multiple customers you must do it through SQL.

Resources