Set a Primary Key for an Entity without ingaffect database - asp.net-mvc

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.

Related

How to rename Primary key Column in code first approach in ASP.net MVC?

I am using EF code first approach. I need to rename my PK column name.
public class classname
{
[Key]
public int OldId { get; set; }
}
I need to change OldId to NewId. I tried renaming my OldId to NewId, I tried updating my database with Migration but that didn't help.
I tried renaming both in column name and model and again when I tried to update my database I still get error.
How can I rename my primary Key column without losing its data?
Is the question that OldId is not used in your code anymore but is still in your database, or is your problem that it OldId is in your code but has a different column name in your database?
You can use fluent API or data annotations if you want to tell entity framework that the name of property in your DbSet has a different column name in the database:
Fluent API Method
public class MyDbContext : DbContext
{
public DbSet<ClassName> ClassNames {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Tell entity framework that you are now building ClassName:
var classNameConfig = modelBuilder.Entity<ClassName>();
// ClassName has an int primary key in OldId:
classNameConfig.HasKey(className => className.OldId);
// "columnX" in the database corresponds with property OldId
classNameConfig.Property(className => className.OldId)
.HasColumnName("columnX");
}
}
Of course in this specific example this can be concatenated into one statement.
The nice thing about fluent API is that you disconnect your classes from the actual database representation. This hides how the actual database names its columns, column order, min size, max size etc from the user of the DbSets.
Just specify a different DbContext, and you can use the same classes with a different Db.
For instance, if you want to use the same entity framework classes in different databases:
class BaseContext : DbContext
{
public DbSet<MyClass> MyClasses {get; set;}
}
// context to be used with database X:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(
DbModelBuilder modelBuilder)
{
// I want to use "columnX" for property A, which is optional:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnX")
.IsOptional();
}
}
// context to be used with database Y:
class DataBaseXContext : BaseContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// I want to use "columnY" for property A, which is required:
modelBuilder.Entity<MyClass>
.Property(p => p.A)
.HasColumnName("columnY")
.IsRequired();
}
}
Data Annotations Method
If you are absolutely sure you want your classes to be used in only one database, with one pre-defined model, you could use Data Annotations.
However, your question shows that it is not uncommon that the same classes will be used in a different database model. So, although this method is very commonly used, I urge you to reconsider a decision to use Data Annotations.
public class classname
{
[Key]
[Column("ColumnX")]
public int OldId { get; set; }
}
changing the Identity column may lead to instability and you cant change anything with the column unless you kill all the Key constraints (all table relation ship)
t will be tooo complicated i would advice you that if data isnt Important then just delete the database and re run migraions it will recreate the database again
The name of the entity property can be different from the name of the database column.
If you need to change the name of the column on the database you can do it with the DBMS manager (SQL Server Enterprise Manager if you are using SQL Server) or running the proper DDL statement (sp_rename on SQL Server) then set the new column name on the property using the attribute ColumnAttribute
[Column("NewId")]
[Key]
public int OldId { get; set; }
If you need to change the name in the code but not on the database you can do a similar thing
[Column("OldId")]
[Key]
public int NewId { get; set; }
In this case you should do a refactor (rename with F2 if you have standard visual studio Keys or Ctrl+R, R if you are using resharper)
If you need to change both you can do both.

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.

Access a table of a separate database using entity framework

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.

Entity Framework Code First : One-To-One association using Annotations

I am having .NET MVC 5 and Identity...
I am trying to get a one to one relationship for my Member class to my MemberInfo class..
So, My classes looks something like this:
IdentityUser is in the Microsoft.AspNet.Identity.EntityFramework namespace with string Id as its ID.
public class GRNUser : IdentityUser {
....
....
}
public class MemberUser : GRNUser {
public virtual Member MemberInfo {get; set; }
}
public class Member {
public int ID {get; set; }
public string MemberUserID {get; set; }
public virtual MemberUser MemberUser { get; set; }
}
In my Context, I have this
modelBuilder.Entity<Member>().HasRequired(m => m.MemberUser)
.WithOptional(u => u.MemberInfo);
So, the MemberUser and Member should be able to navigate to and from each other using the MemberUser's ID property and Member's MemberUserID property.
However, when my Database is created, it has an additional column "MemberUser_Id" instead of using my MemberUserID that I specified. How do I make it use "MemberUserID" that I specified?
I've tried using a few combination so of the ForiegnKey Data Annotation, but keeps on getting this error:
Member_MemberUser_Source: : Multiplicity is not valid in Role 'Member_MemberUser_Source' in relationship 'Member_MemberUser'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
I don't know whether i understood you right or not, but i'l do my best to help.
(I'l assume that you work with code first migration)
If you want to make a one-to-one relation, why not try to make a standalone entity for your info which will have a foreign key for the user entity and that foreign key will be annotated as the primary key of the entity?
Another way is why just not add whatever attributes you like to the Application User entity and work with it?
In any case i might have misunderstood your purpose, so please feel free to explain further since your post is a bit confusing.

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