Map names for generated relationship tables in EF code first - entity-framework

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

Related

Entity Framework 6 adds "set" at the end of every entity

After creating a database model with Entity Framework 6 that looks like this (I am aware that .NET Core is out):
EF generates this code:
public virtual DbSet<User> User { get; set; }
public virtual DbSet<Statevalues> Statevalues { get; set; }
in the model context but also creates tables in the database that are called:
StatevaluesSet
UserSet
Why is it using Set at the end of each name?
I've tried it with EntityFramework by Microsoft version 6.2.0. with a simple DbContext with Schools and Students, and I only got a table named Schools and a table named Students.
To override standard table naming, override DbContext.OnModelCreating.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// give table Schools a special name:
modelBuilder.Entity<School>()
.HasEntitySetName("MySpecialSchools");
}

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

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

EF "The member with identity X does not exist in the metadata collection" (and NopCommerce)

First of all and as you can see in the title, I'm designing a plugin for nopCommerce. I believe that the problem is not related to it (but with Entity Framework) but I'm not really sure.
My plugin has access to data, and nopCommerce let's me create my own context, creating the required tables and relations.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ParentMap());
modelBuilder.Configurations.Add(new ChildMap());
}
Conceptually, what I would like to have is:
ROOT TABLE ----(1:N)---- CHILDTABLE ----(1:1)---- EXISTING NOPCOMMERCE TABLE
And the tables and columns created in the DB seems correct to me. The mappings are pretty simple:
public ParentMap()
{
ToTable("TableA");
HasKey(m => m.Id);
Property(m => m.SomeProperty);
HasMany(m => m.Child).WithRequired(s => s.Parent).WillCascadeOnDelete();
}
public ChildMap()
{
ToTable("TableB");
HasKey(m => new { m.Id });
HasRequired(m => m.NopCommerceEntity);
HasRequired(m => m.Parent);
}
Till this point, everything seems to work pretty well, things get registered and the application starts. When I try to insert or update anything that has relation with the nopCommerce entity, I get the following exception:
"The member with identity 'Namespace.ChildObject_NopCommerceEntity' does not exist in the metadata collection.\r\nParameter name: identity".
I've been thinking that the problem could be related with the fact that I'm not adding other mappings in my OnModelCreating. I've tried to add all the related mappings there but I get the same exception.
It's a bit complicated. I'd be very greatful for your help & time :)
You are right this issue related to Entity Framework because EF does not support cross-project POCO relations. You have to remove any property that has an entity from NopEntities in your plugin and instead use an Id of that entity as int as below :
public int ProductId { get; set; }
instead of
public virtual Product Product { get; set; }
and in the mapping you should not specify the relationship between your entity and the Nop.
I think you can still use the following relation in your child class
public int ProductId { get; set; }
public virtual Product Product { get; set; }
but when you save or update the child class, instead of setting
child.Product = product
instead set the following
child.ProductId = product.Id
and also i think in your PluginObjectContext plugin class inherits from NopObjectContext.

EF Code first and optional:optional relationship

According to msdn article, the following should create an optional:optional relationship, but instead it creates optional:many relationship. Is the article wrong?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Optional_1>()
.HasKey(o1 => o1.id1);
modelBuilder.Entity<Optional_2>()
.HasKey(o2 => o2.id2);
modelBuilder.Entity<Optional_1>()
.HasOptional(o1 => o1.Dependent)
.WithOptionalPrincipal(o2 => o2.Principal);
}
public class Optional_1
{
public int id1 { get; set; }
public Optional_2 Dependent { get; set; }
}
public class Optional_2
{
public int id2 { get; set; }
public Optional_1 Principal { get; set; }
}
thank you
The table might look like one to many, but Entity Framework will enforce it as optional:optional because of the navigation properties. Since the navigation property is only a single object and not a collection, there is no way to add multiple.
If you look at the generated tables, it creates a nullable foreign key to your principal table (Optional_1). This allows you to create an Optional_2 that is not associated with an Optional_1.
If you were to insert multiple rows into Optional_2 that have the same foreign key to Optional_1 outside of EF, there wouldn't be anything preventing it from going through. If you were to try and load these entities you would get an error. You can't add a unique index to the column because it needs to allow NULL since it is optional.

EF Codefirst fails to work with partial tables of northwind database

I could not work with employee table of Northwind database alone.
below code throws error as
"Unable to determine composite primary key ordering for type
'Northwind.Order_Detail'. Use the ColumnAttribute or the HasKey method
to specify an order for composite primary keys."
but it works fine, if I consider Order_details and other tables as well. and HasKey for OrderDetails table.
My Question is, is it not possible to work with few tables (Employee table alone in this case) using EF.
public partial class NorthwindEntities : DbContext
{
public NorthwindEntities()
: base("Northwind")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
SetupModels(modelBuilder);
}
public DbSet<Employee> Employees { get; set; }
}
Anand
Master table has navigation property to Order , Order details tables. that causes this error. after removing navigation properties in Employee table, it works fine.