EF Code First table naming issues - c#

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.

Related

Disabling Column in Entity Framework Code First

I'm using Entity Framework to insert data into 2 different databases. There are a few columns that are present in one of the databases but not the other. Their data types are not nullable (int and float).
I don't use these columns (when they are present) in my code. Meaning I only insert 0 as the data for them but I can't send null obviously.
Is there a way for me to insert data with ease without creating 2 different versions of my app for these? Ideally I'd like to just have one model with something like an attribute that says insert 0 in this column if it's available.
If your application runs only against one database, then you can just use an IF statement in your OnModelCreating that uses the Fluent API to .Ignore() the missing properties.
public class MyDbContextWithMissingColumns: MyDbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (myConfig.UseDatabaseWithoutSomeProperties)
{
modelBuilder.Entity<Foo>().Ignore(f => f.SomeProperty);
}
base.OnModelCreating(modelBuilder);
}
}
If a single instance of your application connects to both databases, then you have to use separate DbContext subtype, as OnModelCreating only runs for the first instance of a DbContext type in an AppDomain.
EG:
public class MyDbContextWithMissingColumns: MyDbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().Ignore(f => f.SomeProperty);
base.OnModelCreating(modelBuilder);
}
}
In the repository for the database with the restricted fields create the entity:
public class MyClass
{
int MyCommonClassID {get; set;}
string Name {get; set;}
[NotMapped]
string PhoneNumber {get; set;}
}
Where the attribute [NotMapped]. is used that field will not appear in the database but you can use it everywhere else. That wat you determine what gets written at the lowest level and your application doesn't care.

generating table code first not generating table on application run

I have a site. using COde first. My add-migration command producted following code.
public partial class StudentEntity : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Student",
c => new
{
id = c.Int( nullable: false, identity: true),
name = c.String(),
})
.PrimaryKey(t => t.id);
}
Now I want to deploy my site so when site runs the first time I want the Student table to get generated in DB(SQL server).
Right now when I run the site it does not create any table. How can I do this? I dont want any seed data to initialize with
My db context class
public partial class flagen:DbContext
{
public flagen() : base("name=cf2")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
//old entity
public virtual DbSet<flag> flags { get; set; }
//new entity
public virtual DbSet<Student> students { get; set; }
}
Then I tried to use Context so table get created. It throws error "The model backing the 'flagen' context has changed since the database was created. Consider using Code First Migrations to update the database "
The I added following two lines to dbcontext class
Database.SetInitializer<flagen>(null);
base.OnModelCreating(modelBuilder);
now it says "invalid object name students"
any solution that works?
One solution could be to define a Initializer that will migrate your database to last existing migration you added. Therefore all tables will be created and the Seed method of the Configuration will be executed too - you could use it for seeding data.
With the following example your database will be updated to last existing migration (and therefore creates all tables) on first initialization of the data context. (var dbContext = new MyDatabaseContext())
In my opinion a much cleaner way than to use AutomaticMigrationsEnabled = true that you could check out too. ;)
As mentioned here is an example that will use the MigrateDatabaseToLatestVersion initializer with the defined behavior.
public partial class MyDatabaseContext : DbContext
{
public virtual DbSet<Student> students { get; set; }
public MyDatabaseContext() : base("MyDatabaseContextConnectionString")
{
System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDatabaseContext, Migrations.Configuration>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// here we want to define the entities structure
}
}
You will find some more information about the initializer itself here (MSDN
- MigrateDatabaseToLatestVersion) and here (Entity Framework Tutorial - Code-First Tutorials - Automated Migration) is another example with some more background information and examples.
The answer of this question is to use T4 templates. After searching the web I got the answer that nobody could on SO. Shame...
https://archive.codeplex.com/?p=t4dacfx2tsql

Entity Framework Code First table naming issue, singular confilcts with Plural

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

Entity Framework throws exception - Invalid object name 'dbo.BaseCs'

I've followed Adam's answer here and the Entity Framework now works and the Seed() method also works.
But when I try to access the database like this:
public User FindUserByID(int id)
{
return (from item in this.Users
where item.ID == id
select item).SingleOrDefault();
}
.............................................................................
// GET: /Main/
public ActionResult Index(int? id)
{
var db = UserDataBaseDB.Create();
if (!id.HasValue)
id = 0;
return View(db.FindUserByID(id.Value));
}
It throws an exception at return (from item in this.Users stating:
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.BaseCs'.
I've tried replacing it with:
return this.Users.ElementAt(id); but then it throws this exception.
LINQ to Entities does not recognize the method 'MySiteCreator.Models.User ElementAt[User](System.Linq.IQueryable1[MySiteCreator.Models.User], Int32)' method, and this method cannot be translated into a store expression.`
Can anyone help me?
Exception Details: System.Data.SqlClient.SqlException: Invalid object name 'dbo.BaseCs'
This error means that EF is translating your LINQ into a sql statement that uses an object (most likely a table) named dbo.BaseCs, which does not exist in the database.
Check your database and verify whether that table exists, or that you should be using a different table name. Also, if you could post a link to the tutorial you are following, it would help to follow along with what you are doing.
It is most likely a mismatch between the model class name and the table name as mentioned by 'adrift'. Make these the same or use the example below for when you want to keep the model class name different from the table name (that I did for OAuthMembership). Note that the model class name is OAuthMembership whereas the table name is webpages_OAuthMembership.
Either provide a table attribute to the Model:
[Table("webpages_OAuthMembership")]
public class OAuthMembership
OR provide the mapping by overriding DBContext OnModelCreating:
class webpages_OAuthMembershipEntities : DbContext
{
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
var config = modelBuilder.Entity<OAuthMembership>();
config.ToTable( "webpages_OAuthMembership" );
}
public DbSet<OAuthMembership> OAuthMemberships { get; set; }
}
If you are providing mappings like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ClassificationMap());
modelBuilder.Configurations.Add(new CompanyMap());
modelBuilder.Configurations.Add(new GroupMap());
....
}
Remember to add the map for BaseCs.
You won't get a compile error if it is missing. But you will get a runtime error when you use the entity.
It might be an issue about pluralizing of table names. You can turn off this convention using the snippet below.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
If everything is fine with your ConnectionString check your DbSet collection name in you db context file. If that and database table names aren't matching you will also get this error.
So, for example, Categories, Products
public class ProductContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
should match with actual database table names:
EF is looking for a table named dbo.BaseCs. Might be an entity name pluralizing issue. Check out this link.
EDIT: Updated link.
My fix was as simple as making sure the correct connection string was in ALL appsettings.json files, not just the default one.
Instead of
modelBuilder.Entity<BaseCs>().ToTable("dbo.BaseCs");
Try:
modelBuilder.Entity<BaseCs>().ToTable("BaseCs");
even if your table name is dbo.BaseCs
For what it is worth, I wanted to mention that in my case, the problem was coming from an AFTER INSERT Trigger!
These are not super visible so you might be searching for a while!
I don't know if is the case,
If you create a migration before adding a DbSet your sql table will have a name of your model, generally in singular form or by convention we name DbSet using plural form.
So try to verifiy if your DbSet name have a same name as your Table. If not try to alter configuration.
Most probably the translated SQL statement can't find the table name.
In my case, the table was assigned to a different schema. So, in the model you should enter the schema definition for the table like this:
[Table("TableName", Schema = "SchemaName")]
public class TableName
{
}
You have to define both the schema and the table in two different places.
the context defines the schema
public class BContext : DbContext
{
public BContext(DbContextOptions<BContext> options) : base(options)
{
}
public DbSet<PriorityOverride> PriorityOverrides { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.HasDefaultSchema("My.Schema");
builder.ApplyConfiguration(new OverrideConfiguration());
}
}
and for each table
class PriorityOverrideConfiguration : IEntityTypeConfiguration<PriorityOverride>
{
public void Configure(EntityTypeBuilder<PriorityOverride> builder)
{
builder.ToTable("PriorityOverrides");
...
}
}
In EF (Core) configuration (both data annotations and fluent API), the table name is separated from the schema.
Remove the "dbo." from the table name and use the ToTable overload with name and schema arguments:
.ToTable("MyUsers", "dbo");
Or taking into account that dbo is the default schema (if not configured differently), simply:
.ToTable("MyUsers");
As it is currently, it considers table dbo.dbo.MyUsers which of course does not exist.
The solution is very simple.
Just run the migration. Make sure you have the migrations folder with the code. Then on the Configure method of startup, put this code first in you method body:
using (IServiceScope scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
scope.ServiceProvider.GetService<FRContext>().Database.Migrate();
}
This update the database, but its base in the migrations folder. I created the database, but if it does not find the migration folder with the files, it will create the database without tables, and you app will break at runtime.
Use table annotation in your class and use the name same as the name of view or table in the database
[Table("tbl_Sample")]
public class tblSample
{
//.........
}
In the context definition, define only two DbSet contexts per context class.
Wrong DB configuration in my tests while I was looking at the configuration from the project being tested.
In my case, I put the wrong ConnectionString name in connectionString Configuration in Startup.cs, Your connectionstring name in startup.cs and appsettings.json must be the same.
In appsettings.json:
In startup.cs:
Thats why when i made query using this context, it found no connectionstring from the appsettings when there was a wrong name. Consequently, it results Invalid Object Name 'a db table name'.

EF 4.1 Code First POCOs Library

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

Categories

Resources