entity framework plural table names - entity-framework

I am trying to get EF 5 to generate singular table names. I have the following code in my DbContext...
public partial class LiveoModelContainer : DbContext
{
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
We are using Model First, and have our own generated code to follow our internal development patterns. So we are not using the out of the box code gen that comes with EF. I have set pluralization to false in the edmx properties, in the Database Tools/O/R Designer, and removing the convention in the OnModelCreating above. However, the table names remain plural.
How do I fix this?

Related

How to create View (SQL) from Entity Framework in ABP Framework

My situation is that I need to query from another database and show the result in my application. Both databases are on the same server. I came up with an idea on creating SQL-View in my database which would query the other database for values that I want. But I am not quite sure on how I can create or map SQL-View from the ABP framework?
I am using the full .Net framework with the Angular template.
Creating View is not directly supported in EF. So you can try the below approach.
Create an empty Migration using Add-Migration.
Write you Create View script in Up method of generated migration
and run the script using context.Database.ExecuteSqlCommand method.
Declare your class and use Table as you do for your model class.
[Table("YourViewName")]
public class YourClassName
{
}
Ignore your view class like this
modelBuilder.Ignore<yourClassName>(); in OnModelCreating method.
Run Update-Database in Package Manager Console.
Create your table view in the database. Then using EF FluentAPI to config the view mapping. Here is the sample code:
1. Create POCO class to map:
public class YourView
{
public int Id { get; set; }
public string Value { get; set; }
}
2. EF FluentAPI mapping configuration:
Create map class:
public class YourViewMap : IEntityTypeConfiguration<YourView>
{
public void Configure(EntityTypeBuilder<YourView> builder)
{
builder.ToTable("YourViewName");
}
}
Add mapping configuration to your DbContext (such as AbpCoreDbContext). Override OnModelCreating method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new YourViewMap ());
base.OnModelCreating(modelBuilder);
}
3. Get data:
using IRepository<YourView> to query data from the view.
P.S: related question how to use views in code first entity framework
Create a new DbContext for your legacy database. You can have multiple DbContext in an ABP application. Each DbContext have its own connection string. Creating view is kinda hackish.

Entity Framework model first: create UNIQUE constraint programmatically

I am trying to add a UNIQUE constraint to the "Username" property of my "UserAccount" entity/class. With code-first, that would be no problem, but for model-first, I can't find anything on how to achieve that.
The designer does not support this feature. I cannot use annotations because the entity classes are auto-generated. I cannot use Fluent API because the OnModelCreating() method is not called in model-first and thus I have no DbModelBuilder instance.
The only thing I can think of is executing some kind of manual SQL statement at application start that creates the UNIQUE constraint, which kind of defeats the purpose of EF.
Here is my current DbContext class:
public partial class UserAccountsModelContainer : DbContext
{
public UserAccountsModelContainer()
: base("name=UserAccountsModelContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<UserAccount> UserAccounts { get; set; }
}
I won't even bother to post the UserAccount class since it's auto-generated and shouldn't be modified (I know that the DbContext is also auto-generated, but modifying it is possible).
Any help on this is appreciated!
First I will recommend you to switch to Entity Framework Code First, too. It gives you much more controll about every thing that is possible with EF.
I never used it before, but I know Model Conventions. They are applicable to the model configuration. Maybe it will be an approach to set up a convention for a defined model type/property that should be configured as unique constraint.
Based on the following it should be possible to modify the set up of model first on creating database.
Model Conventions are based on the underlying model metadata. There
are conventions for both CSDL and SSDL. Create a class that implements
IConceptualModelConvention from CSDL conventions and implement
IStoreModelConvention for SSDL convention.
Source: http://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx
There are two types of model conventions, Conceptual (C-Space) and
Store (S-Space). This distinction indicates where in the pipeline a
convention is executed. A C-Space convention is applied to the model
that the application builds, whereas an S-Space convention is applied
to the version of the model.
Source: https://entityframework.codeplex.com/wikipage?title=Custom%20Conventions
Some more example implementations incl. explainations are findabe on msdn. I guess they are very helpful for your case.
One example from MSDN:
public class DiscriminatorRenamingConvention : IStoreModelConvention<EdmProperty>
{
public void Apply(EdmProperty property, DbModel model)
{
if (property.Name == "Discriminator")
{
property.Name = "EntityType";
}
}
}
It will rename the column Discriminator into EntityType. It is a very simple example but you could modify it to solve your problem to:
public class ModelBasedConvention : IConceptualModelConvention<EdmProperty>
{
public void Apply(EdmProperty property, DbModel model)
{
if (property.Name == "Username"
&& property.DeclaringType.GetType() == typeof(UserAccount))
{
property.AddAnnotation("UniqueKey", property);
}
}
}

Entity Framework - Existing Database, classes in seperate library

I'm looking for information about using entity framework with an existing database, but to keep my poco classes in another library.
I've done this a number of times in the past, but I've always ended up with my model classes in my data access library using EF and my domain classes in a separate library. Inevitably this meant writing code to translate between my domain classes and my model classes. This seems pointless and inefficient since the classes are usually almost identical.
Can anyone point me to a walkthrough keeping my classes are materialized by EF in a separate library? I would need to be able to do some minor name correction (eg Filter_Rule --> FilterRule). I would also like to be able to keep anything EF specific in the data access library so that I can swap out the data access library if I need to.
Thanks,
Jason
This should be quite straightforward. Create a DbContext code-first style as normal, adding DbSets and configurations as necessary to tell EF about your database. Set your initializer to null so it doesn't try to mess with your existing database, and voila...
public class YourContext : DbContext
{
public DbSet<YourPoco> YourPocos { get; set; }
static YourContext()
{
Database.SetInitializer<YourContext>(null);
}
public YourContext() : base("database_name")
{
}
protected override void OnModelCreating(DbModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<YourPoco>().Property(x => x.FilterRule).HasColumnName("Filter_Rule");
//OR
builder.Configurations.Add(new YourPocoConfig());
//OR
builder.Configurations.AddFromAssembly(typeof (YourContext).Assembly);
}
}
public class YourPocoConfig : EntityTypeConfiguration<YourPoco>
{
public YourPocoConfig()
{
HasKey(x => x.Id);
Property(x => x.FilterRule).HasColumnName("Filter_Rule");
}
}
If you are worried about getting everything to match your database structure, you can use Entity Framework Tools for Visual Studio to reverse engineer your models, then match the configuraiton or copy the generated POCO's into your other library and convert the data annotations into respective EntityTypeConfiguration classes to keep the POCO's clean.
MSDN document on reverse engineering code-first.

How to exclude one table from automatic code first migrations in the Entity Framework?

I'm using the Entity Framework in the Code First mode with automatic migrations enabled. Now, I have one entity whose table should not be managed (migrated) by the EF. Is there a way of disabling automatic migrations for one specific entity (i.e. table)?
This is now possible in EF Core 5.0 using the ExcludeFromMigrations() method, but strangely enough you have to call the ToTable() method and then use the TableBuilder.
https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-efcore-5-0-rc1/#exclude-tables-from-migrations
public class ReportingContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable(nameof(Users), t => t.ExcludeFromMigrations());
}
}
Another option that worked for me in EFCore 5.0 is to use SetIsTableExcludedFromMigrations:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>().Metadata.SetIsTableExcludedFromMigrations(true);
}
My TEMPORARY solution, only for dev environments.
I have a separate script that runs migration and program run does not check them. So in unexpected case I was possible to invoke Ignore<ContactView>() and run migrations with this line. When it was completed, I removed this line!
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// comment out this code after migrations are done
modelBuilder.Ignore<ContactView>();
}
It is possible by using another DbContext to access the table in question. Migrations are bound to one DbContext (see Is it possible to have automatic migrations for one DbContext and not for another in the same project?).
Not sure if this is the OP's exact scenario, but I had a table that I did not want a migration generated for. I accomplished this by using ToView instead of ToTable within the DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyTable>(entity => {
// Migration will not be generated for this table
entity.ToView("MyTable", "dbo");
entity.Property(e => e.FooBar).HasColumnType("DECIMAL(19,9)");
});
}
It feels a bit hacky to me, but maybe it's not -- because, after all, I'm just trying to "view" the table, not write to it...
[Tested with .NET Core EF 3.1.3]
You want to use the [NotMapped] annotation on that class/entity.

Can I specify global mapping rules in Entity Framework Code First?

I'm building an app in ASP.NET MVC 4 using Entity Framework Code First, and for simplicity I'm inheriting all models that will be stored in the database from a BaseEntity that has a Guid, a DateCreated, a LastEditDate and a other useful properties like that. Now, I know that I can tell EF to map these inherited properties like so:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Map(m =>
{
m.MapInheritedProperties();
});
modelBuilder.Entity<Product>().Map(m =>
{
m.MapInheritedProperties();
});
}
It seems silly to have to do this for every item, though. Is there a way I can apply this rule to all entities in one?
It has been stated correctly that it's not necessary to do global mapping in this specific case, because EF will map the properties for each individual type as long as you don't make BaseEntity part of the model.
But your question title is stated more generally and yes, it is possible to specify global mapping rules if you configure the mappings by EntityTypeConfigurations. It could look like this:
// Base configuration.
public abstract class BaseMapping<T> : EntityTypeConfiguration<T>
where T : BaseEntity
{
protected BaseMapping()
{
this.Map(m => m.MapInheritedProperties()); // OK, not necessary, but
// just an example
}
}
// Specific configurations
public class UserMapping : BaseMapping<User>
{ }
public class ProductMapping : BaseMapping<Product>
{ }
public class TempModelsContext : DbContext
{
// Add the configurations to the model builder.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new UserMapping());
modelBuilder.Configurations.Add(new ProductMapping());
}
// DbSets
...
}
Notes:
In Entity Framework 6 (for .Net framework) has custom code first conventions by which many global mapping rules can be configured.
Entity Framework core has even more extensive tools for configuring global mappings.
Such a mapping - called Table-Per-Concrete-Type (TPC) inheritance mapping - only makes sense if you really want to leverage polymorphism, for example if you want to load a list of say 10 BaseEntity objects and expect that the actual type gets materialized so that the list contains 3 User entities and 7 Product entities.
Would such a query ever have any business relevance in your application? Looking at your BaseEntity I can only see that querying all objects that - for example - have been created at a specific date, no matter which type the object has (if it's derived from BaseEntity), could be useful. Do you need that? Also keep in mind how complex such a query would be. The SQL must query for almost all tables in your database and then union the result.
I would use inheritance mapping only if it has a real business meaning (for instance: Person which has meaningful properties like address, phone, email, etc. on its own and Employee that is derived from Person and adds a Salary and HiredDate property, etc.).
In your case I would use the BaseEntity only as a base type of your entity classes and don't specify any mapping at all for this class. EF will still map the inherited properties, but as part of the User and Product entity, etc., not as its own entity. I wouldn't even call it "Base Entity" but ... I don't know... maybe EntityBase (meaning: the base (class) of all entities, but not an entity itself).