I would like to mention that i am new to EF.
I am creating the Data Access library with EF 4.1.
For each Entity I have two tables for translation target.
ex : Events ==> Event_ar for Arabic and Event_en for English.
First Problem : I have an error if i write two DbSets of same Entity Type
so I did this work around which is absolutely not nice :
public class Event_en : Event { }
public class Event_ar : Event { }
public class DB : DbContext
{
public DbSet<Event_ar> Events_ar { get; set; }
public DbSet<Event_en> Events_en { get; set; }
}
I would like to know if there is a solution for it?
Second one
The Entity should be same name as a table, otherwise i have an error.
Ex : "dbo.Event_ar" should have a POCO "Event_ar"
It should be the name of the property that has the same name of the table.
Here : dbo.Events_ar ==> POCO "Events_ar"
Why I can't manipulate the names? Any solution?
I'm not sure if your solution is going in the right direction. It doesn't feel right to have a table for every language - you could simply add another column to the event table that specifies what the language is?
The you could use this column to retrieve the row with the desired language.
About tables and POCO entity names, you can override the table the entity is mapped to either through the use of a System.ComponentModel.TableAttribute at the class elvel, but to maintain POCO-ness I like to use EntityTypeConfiguration classes and specify the table name.
for example:
public class CurrencyConfiguration : EntityTypeConfiguration<Currency>
{
public CurrencyConfiguration()
{
this.ToTable("Conv", "Ref");
}
}
Then you add it to the model builder in the OnModelCreating override method on the DbContext.
public class MyContext : DbContext
{
public DbSet<Currency> Currencies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CurrencyConfiguration());
}
}
Related
so I have 2 different DbContext (ef 6.1.3 code first)
FirstDbContext
SecondDbContext
each context contains a SbSet Users that maps the user table in the corresponding database
NOTE : the data is different, DbFirst User is not DbSecond User!!
I have an abstract repository:
public abstract class Repository<TContext> where TContext : DbContext
{
public Repository(TContext ctx)
{
}
}
and 2 repositories :
public FirstRepo : Repository<FirstDbContext>
{
public FirstRepo(FirstDbContext ctx):base(ctx)
{
}
}
public SecondRepo : Repository<SecondDbContext>
{
public SecondRepo(SecondDbContext ctx):base(ctx)
{
}
}
I Have 2 different MSSQL databases related to the contexes:
DbFirst
DbSecond
I'm using dependency injection to add scoped repository and contexes, 2 database, 2 different connection.
I expected that my .Net Core application would use 2 Models
but once i get data from both the context i get
NotSupportedException: The type 'First.User' and the type
'Second.User' both have the same simple name of
'User' and so cannot be used in the same model.
Why the same model?
I know that in the same model I should have different names because EF does not look for namespaces, but in that case I shouldn't have this kind of issue.
EDIT #1 :
If I use one of the repository alone everything works as expected so i'm sure that there isn't any mispelled namespace
If I use the repositories all together i got this error, for example
var top10 = FirstRepo.GetTop10().ToList();
var sam = SecondRepo.GetByName<Second.User>("sam");
EDIT 2 (#Steve Green):
//Note that I'm not trying to do this :
public class MyTextContext : DbContext
{
public DbSet<Test.Security.Question> Security_Question { get; set; }
public DbSet<Test.Forms.Question> Forms_Question { get; set; }
}
// What I need is something like this :
public class SecurityContext : DbContext
{
public DbSet<Test.Security.Question> Question { get; set; }
}
public class FormsContext : DbContext
{
public DbSet<Test.Forms.Question> Question { get; set; }
}
Important note
If I manually ignore the "other" entity in both of the context everything works
I Remark that the context are not only in different namespaces, but also different assemblies...
// this is working!! .___.
// but i don't want to add a reference to a project just to exclude a class... it's unacceptable
public class FirstDbContext : DbContext
{
public DbSet<First.User> Users {get;set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<Second.User>();
}
}
public class SecondDbContext : DbContext
{
public DbSet<Second.User> Users {get;set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<First.Usere>();
}
}
Any suggestion different from renaming the table will be appreciated
Thanks
I have a SQL view that I am pulling in with entity framework. The view represents two existing objects that are joined together. I figured the best way to do this would be to have object inherit the other object.
I'm getting this error:
System.Data.Entity.Core.EntityCommandExecutionException: An error
occurred while executing the command definition. See the inner
exception for details. ---> System.Data.SqlClient.SqlException:
Invalid column name 'Discriminator'.
Here is what I have setup:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Class1>()
.ToTable("mySQLView", "TEST")
.HasKey(r => new { r.Property1 });
modelBuilder.Entity<Class1>().Property(r => r.Property1).HasColumnName("Key1");
modelBuilder.Entity<Class1>().Property(r => r.Property2).HasColumnName("Column2");
modelBuilder.Entity<Class1>().Property(r => r.Property3).HasColumnName("Column3");
modelBuilder.Entity<Class1>().Property(r => r.Property4).HasColumnName("Column4");
}
Here are my two classes:
public class Class1 : Class2
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class Class2
{
public string Property3 { get; set; }
public string Property4 { get; set; }
}
Class2 is being utilized by separate DB calls. Class1 is only being used in one of those calls. Any help on how to structure my classes or setup EF correctly would be greatly appreciated!
The problem is that you are using TPH (Table Per Hieararchy) that is a way that EF uses to implement inherithance. Using TPH EF needs a column named discriminator to associate the record with a specific entity of the hierarchy.
In your case I think you need TPT (but it depends on what you want access to classes). To do it just set the name of the Class2 table (or view) using ToTable. Otherwise you can add Discriminator column but you should leave EF to handle it.
With Entity Framework I can map related tables as a class inheritance and There are three different approaches to representing an inheritance hierarchy (by weblogs):
Table per Hierarchy (TPH)
Table per Type (TPT)
Table per Concrete class (TPC)
The site mscblogs has a nice explanation for each one of these approaches.
I'm trying to understand how to map my tables using the approach TPT (Table per Type), but unlike the example of mscblogs, I need to do the mapping for fluent programming like:
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
public class BillingDetailMap : EntityTypeConfiguration<BillingDetailEntity>
{
public BillingDetailMap()
{
// ...
this.Property(t => t.Number).HasColumnName("Number");
// ...
}
}
// ...
I'm searching for several hours but I couldn't find anything. I found many examples how to do this with diagram, with attributes and others, but nothing with fluent api.
How to Mapping TPT in Entity Framework 4.1 Fluent API?
Mapping the Table-Per-Type (TPT) Inheritance
In the TPT mapping scenario, all types are mapped to individual
tables. Properties that belong solely to a base type or derived type
are stored in a table that maps to that type. Tables that map to
derived types also store a foreign key that joins the derived table
with the base table.
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");
Source
Check also my answer on previous question, hopefully it helps.
update complete example
public class AppContext : DbContext
{
public DbSet<Item> Items { get; set; } // --> this dbset is required for TPT, if removed it will become TPCC
public DbSet<Food> Books { get; set; }
public DbSet<Book> Foods { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ItemMap());
modelBuilder.Configurations.Add(new BookMap());
}
}
public class ItemMap : EntityTypeConfiguration<Food>
{
public ItemMap()
{
ToTable("Foods");
}
}
public class BookMap : EntityTypeConfiguration<Book>
{
public BookMap()
{
ToTable("Books");
}
}
public abstract class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Food : Item { }
public class Book : Item { }
I have 2 table which I'm trying to access in MVC, one called Employees and one called Accountable. This is my code: -
public class dbEntity: DbContext
{
public dbEntity(): base("name=dbEntity") {}
public DbSet<Accountable> Accountable { get; set; }
public DbSet<Employees> Employees { get; set; }
}
The problem is the code complains that it can't find the table 'Accountables', I know I can add this line: -
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); }
But then the code complains that it can't find 'Employee'. At the moment it is not practical to rename the tables, is there another way around it?
Thanks
Add a data annotation of your table's name in the database to your context class.
[Table("TableName")]
I have a project built using EF code first. It also uses forms authentication. Until recently the membership database and the application database were being developed separately, but I want to combine them into one database for simplicity.
One of the classes in my code first model is called "Application" so the EF-generated table is called "Applications" which conflicts with a membership table of the same name. This is an example of my current context:
public partial class ExampleContext : DbContext
{
public DbSet<Application> Applications { get; set; }
public DbSet<Status> StatusTypes { get; set; } // notice the name of the property vs the name of the class
}
I thought the table names were based on the names of the properties in the context, because it was generating a table named StatusTypes for all of the Status objects. But if I rename the Applications property to something like MyApplications it is still generating a table named Applications. So clearly it's not just the name of the property and I'm missing something.
My question: how do I get EF to name this table differently?
Couldn't you use the configuration class to do something like this:
public class ApplicationConfiguration : EntityTypeConfiguration<Application>
{
public ClientConfiguration()
{
ToTable("SpecialApplication");
}
}
Then in your context override OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ApplicationConfiguration());
}
This should then force your table to be named SpecialApplication and avoid the conflict
By default, Entity framework code first will generate pluralized names for tables when it builds the db from the model classes. You can override the OnModelCreating method of your db context class specify a different name for the table.
public class YourDBCOntext:DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Applications>().ToTable("MYApplications");
}
}
You can do this globally also so that none of the tables will have pluralized names.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTaleNameConvention>();
}
}
I just renamed the class and it worked. Easiest solution for now.