Is there a way to have class names be different from your table names? - entity-framework

We are using a database created several years ago, and would like to keep the table names the same.
All of our tables are named like: "tbl_Orders" but we would like the class names for the models / controllers / etc. to be Orders / OrdersController / etc. We are mapping the classes to our tables using Entity Framework.
Sorry if this has been asked before, I tried searching but came up empty handed...
Solution:
After some back and forth with Scott Chamberlain, we came to the conclusion that both answers are correct. I went ahead and marked Masoud's answer as accepted, because that is the route I went. Thank's to everyone who helped (especially Scott).

You can use the Table attribute or the fluent api to map between table names in your database and class names
[Table("tbl_Blogs")]
public class Blog
3rd party edit
Entity framework core offers the same option to map tablenames or columns
map tables names
map column names
The mapping can be done by using attributes
[Table("blogs")]
public class Blog
{
[Column("blog_id")]
public int BlogId { get; set; }
public string Url { get; set; }
}
or by using the fluent api
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.ToTable("blogs");
modelBuilder.Entity<Blog>()
.Property(b => b.BlogId)
.HasColumnName("blog_id");
}

You can use following code in your DbContext to map all your entities to your tables:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// TableNameConvention
modelBuilder.Types()
.Configure(entity =>
entity.ToTable("tbl_" + entity.ClrType.Name));
base.OnModelCreating(modelBuilder);
}

Working on EF Core 7.0(5.0+) and this one worked for me.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes())
{
// check if current entity type is child of BaseModel
if (mutableEntityType.ClrType.IsAssignableTo(typeof(BaseEntity)))
{
mutableEntityType.SetTableName($"tbl_{mutableEntityType.ClrType.Name.Pluralize()}");
}
}
base.OnModelCreating(modelBuilder);
}

Related

ignore one table with ef-core migration

I have an ASP.NET Core application. I have structured the application as multiple projects under the solution. In two of the projects I have 2 different contexts for the same database. The problem is I have a table I am using for auditing in both contexts, and this is causing a problem with migration.
My question is:
is there anyway I can make migration ignore creating this table in one of the contexts?
I am getting the error in the following line:
dbContext.Database.Migrate();
in you dbContext you can ignore one or more table using model builder ignore and give the entity class type you want to ignore
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Ignore<YourClassHere>();
}
You can do this by adding onModelCreating method.
public class ApplicationDbContext : DbContext
{
public DbSet<TableName> TableNames { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TableName>().ToTable(nameof(TableNames), t =>
t.ExcludeFromMigrations());
}
}

How to specify Unique Key in EF 7 Code First with Data Annotations

You can specified a Unique Key with Fluent Api:
public class MyContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasIndex(u => u.Nickname)
.IsUnique();
}
}
public class User
{
public int UserId { get; set; }
public string Nickname { get; set; }
}
But can you do it with Data Annotations?
Edit
Methods change in EF7 Beta 8:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Index(u => u.Nickname)
.Unique();
}
I'm afraid create an Index using Data Annotation is not still supported in EF 7. Check this link.
I also tried to find some info related with that subject in the last releases and I couldn't find anything.
EF 7 beta 8 release notes
EF 7 RC1 release notes
I found now a post from one of the EF developers (divega) saying this:
In EF7 we support defining indexes using the fluent API but not an
attribute, at least no yet. The IndexAttribute you are possibly
referring to is something we added to the EF 6.x package at some point
but never really became a standard DataAnnotation.
We don't want to copy the original attribute from EF6 as is because
there are a few things in it that we would like to change. Also,
having it in DataAnnotations directly would likely make more sense
than adding it to the EF7 package.
I should mention though that it is highly unlikely that we will add
IndexAttribute in the EF7 RTM timeframe.
Update 1
Apparently this is a feature that will not be added to EF Core, at least for now.
From EF Core documentation:
Indexes can not be configured using Data Annotations.
But you can do it using Fluent Api:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasIndex(b => b.Url)
.HasName("Index_Url");
}
In the absence of built in support, you can use a custom attribute of your own to annotate model properties and apply in OnModelCreating():
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
var index = prop.PropertyInfo.GetCustomAttribute<IndexAttribute>();
if (index != null)
{
entity.AddIndex(prop);
}
}
}
}
With a simple marker attribute class:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class IndexAttribute : Attribute
{
}
Then in your model class, just add the attribute to create a secondary index:
public class User
{
public int UserId { get; set; }
[Index]
public string Nickname { get; set; }
}

Cannot find plural form of table

For some reason code-first EF7 (vNext) will not use/find the plural form of my table. I have tried adding the table attribute to the model but it does not solve the problem.
[Table("Units")]
public class Unit
If I name the table Unit then no problem. If I name the table Units then it's not found.
What am I doing wrong or missing?
Thank you.
This is how I resolved:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Unit>().ToTable("Units");
}
For Entity Framework 7 beta1, I solved this issue by this way:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Unit>().ForRelational(rb =>
{
rb.Table("Units");
});
}
Entity Framework 7 is being configured using the Fluent API. I created an extension method which maps the table names to their plural form, with the intention to reproduce the EF 6 behavior and to be able to use my existing database while working with EF7.
public static class ModelBuilderExtensions
{
public static void PluralizeNames(this ModelBuilder modelBuilder)
{
var types = modelBuilder.Model.EntityTypes;
foreach (var type in types.Where(type => type.ClrType != null))
{
modelBuilder.Entity(type.ClrType)
.ForRelational()
.Table(type.ClrType.Name.Split('`')[0].Pluralize());
};
}
}
Please note the .Pluralize() extension method. This may be Humanizer you're using or any other extension method which pluralizes your string. (I shamelessly copied https://github.com/srkirkland/Inflector/blob/master/Inflector/Inflector.cs in my project to be able to compile my project with the DNX Core.)
The .Split() part is to deal with the type.ClrType.Name which can output stuff like IdentityUserRole`1.
You can use it like this in your DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.PluralizeNames();
}
Ps; this works for me
Now the ToTable and ForRelational both are missing in beta5 of EF7. So I used the below code.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Role>().ForSqlServer().Table("Role");
}
You need to add "Microsoft.EntityFrameworkCore.Relational" in your project.json and restore your package.
.NET core is broken down in to small pieces for less memory foot print. So you need to explicitly tell what you want.

EF5 : Manual table mapping

How to do manual table mapping in Entity Framework 5 using the Code First approach?
What I mean by table mapping is to associate a table name from the database to an entity class with a different name.
This is pretty simple.
[Table("Foo")]
public class Bar {
// properties
}
For fluent api:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>().ToTable("MyTargetTable");
}

Map names for generated relationship tables in EF code first

I'm giving Code first a try and I have the requirement of a prefix of (all) my tables in db.
In my DbContext I have these entities:
public DbSet<Person> People { get; set; }
public DbSet<Department> Departments { get; set; }
I can successfully map table names for my entities by overriding:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().ToTable("w_people");
modelBuilder.Entity<Department>().ToTable("w_departments");
}
However for tables that created that don't directly map to a table I can't figure out to prefix.
In my example people can belong to many departments so a "non-entity" table is created by EF. (I'm a EF noob so these tables probably have a fancy name) So in my db I get three tables:
w_people
w_departments
PersonsDepartments
The PersonsDepartments table is what I'm after. How can I prefix these generated tables or change name/mapping after generation?
TIA
I have solved this:
modelBuilder.Entity<Person>().HasMany(p => p.Departments)
.WithMany(d => d.People)
.Map(mc => mc.ToTable("w_peopledepartments"));