Im currently looking at migrating from fluent nHibernate to ADO.Net Entity Framework 4.
I have a project containing the domain model (pocos) which I was using for nHibernate mappings. Ive read in blogs that it is possible to use my existing domain model with EF4 but ive seen no examples of it. Ive seen examples of T4 code generation with EF4 but havent come accross an example which shows how to use existing domain model objects with EF4. Im a newby with EF4 and would like to see some samples on how to get this done.
Thanks
Aiyaz
Quick walkthrough :
Create an entity data model (.edmx) in Visual Studio, and clear the "custom tool" property of the edmx file to prevent code generation
Create the entities in your entity data model with the same names as your domain classes. The entity properties should also have the same names and types as in the domain classes
Create a class inherited from ObjectContext to expose the entities (typically in the same project as the .edmx file)
In that class, create a property of type ObjectSet<TEntity> for each of you entities
Sample code :
public class SalesContext : ObjectContext
{
public SalesContext(string connectionString, string defaultContainerName)
: base(connectionString, defaultContainerName)
{
this.Customers = CreateObjectSet<Customer>();
this.Products = CreateObjectSet<Product>();
this.Orders = CreateObjectSet<Order>();
this.OrderDetails = CreateObjectSet<OrderDetail>();
}
public ObjectSet<Customer> Customers { get; private set; }
public ObjectSet<Product> Products { get; private set; }
public ObjectSet<Order> Orders { get; private set; }
public ObjectSet<OrderDetail> OrderDetails { get; private set; }
}
That's about it...
Important notice : if you use the automatic proxy creation for change tracking (ContextOptions.ProxyCreationEnabled, which is true by default), the properties of your domain classes must be virtual. This is necessary because the proxies generated by EF 4.0 will override them to implement change tracking.
If you don't want to use automatic proxy creation, you will need to handle change tracking yourself. See this MSDN page for details
Related
I have built the following model of hierarchy for DB:
public abstract class ApplicationUser : IdentityUser
{ }
public class FirstUser : ApplicationUser
{}
public class SecondUser : ApplicationUser
It is noticeable abstract Application class inherits from ASP.NET Core Identity's not abstarct class IdentityUser.
So my purpose is building different tables for UserFirst and UserSecond only, not for IdentityUser and ApplicationUser.
I tried to configure model the following:
builder.Ignore<IdentityUser>();
builder.Entity<FirstUser>().ToTable("FirstUsers");
builder.Entity<SecondUser>().ToTable("SecondUsers");
However it throws exception: Invalid column name 'Discriminator'
What can I do?
Table per Concrete Type (TPC) or Table per Type (TPT) aren't currently supported in EntityFrameework Core 1.0. Only Table per Hierarchy (TPH) is supported.
TPC and TPT are on the high priority list and may come in EntityFramewor Core 1.1 or 1.2, see the EntityFramework Core Roadmap.
Backlog Features
...
High priority features
...
Modelling
More flexible property mapping, such as constructor parameters, get/set methods, property bags, etc.
Visualizing a model to see a graphical representation of the code-based model.
Simple type conversions such as string => xml.
Spatial data types such as SQL Server's geography & geometry.
Many-to-many relationships without join entity. You can already model a many-to-many relationship with a join entity.
Alternate inheritance mapping patterns for relational databases, such as table per type (TPT) and table per concrete type TPC.
As for your question:
You can't do anything about it. If you absoloutely need this feature, you have to fall back to EntityFramework 6.x, but then you can't target .NET Core and have to target .NET Framework 4.x.
It should be noted here, that Microsoft do not feels (or recommends) to use EntityFramework Core 1.0 yet in production environment, if you require the features used from EF6. It will take several versions (at least 2 minor releases) until EntityFramework Core will get anyway close featurewise to EF6.
So if TPC is absolute requirement, go back to EF6.
Technical stuff aside, performance wise it's prefered to use TPH for mapping inheritance to your database as it avoids unnecessary joins during queries. When you use TPT/TPC every query invovling it will have to perform joins and joins are less performant.
So unless you have to map to a legacy DB designed in that way, you should fall back to TPH.
Table-per-concrete-type (TPC) mapping is now available in EFC 7.0.0 nightly builds.
https://github.com/dotnet/efcore/issues/3170
https://github.com/dotnet/efcore/issues/3170#issuecomment-1124607226
https://learn.microsoft.com/en-gb/ef/core/what-is-new/ef-core-7.0/plan#table-per-concrete-type-tpc-mapping
What you need to try it out:
.NET SDK 7.0.100-preview.4
https://dotnet.microsoft.com/en-us/download/dotnet/7.0
Visual Studio 2022 Preview 17.3
https://visualstudio.microsoft.com/vs/preview/
NuGet
Microsoft.EntityFrameworkCore 7.0.0-preview.4.22229.2
Code example:
ApplicationDbContext:
using Microsoft.EntityFrameworkCore;
namespace WebApplicationNet7.Data
{
public class ApplicationDbContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<RssBlog> RssBlogs { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>().UseTpcMappingStrategy();
modelBuilder.Entity<RssBlog>().UseTpcMappingStrategy();
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
public class RssBlog : Blog
{
public string RssUrl { get; set; }
}
}
Migration will look like this:
Note that RssBlog is missing .Annotation("SqlServer:Identity", "1, 1").
You will probably get a warning that looks like this:
Microsoft.EntityFrameworkCore.Model.Validation[20609]
The property 'BlogId' on entity type 'Blog' is configured with a
database-generated default, however the entity type is mapped to the
database using table per concrete class strategy. Make sure that the
generated values are unique across all the tables, duplicated values
could result in errors or data corruption.
I could not get it to work with either setting
modelBuilder.Entity<RssBlog>().Property(u => u.BlogId).UseIdentityColumn(); or using annotation [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
Since I already have a DB project in my solution, I was wondering can I leverage Entity Framework so that the Web Application may communicate with the database without having to do any migrations, or is migration necessary in order to use the Context of Entity Framework?
If migrating is not necessary then I also won't need the designer (edmx) file, I could just make my models and link them into my context right?
Not necessary at all.
I often write short solutions towards some databases where I just want to add some functionality on the fly. What I typically do is to just open SQL Server Object Explorer in VS2015, Expand the table I'm interested in, and just write a class on the fly, matching the fields that I need.
I.e for a table named "Classes" in the database, I would end up with a class in C#
public class SomeClass
{
public int Id {get; set;}
public string Title {get; set;}
// +other intersting fields
}
Then I simply create a DbContext class pointing to my database:
public class MyContext : DbContext
{
public DbSet<SomeClass> Classes{get; set;}
public MyContext() : base("myConnectionString"){}
}
That's it. No need for migrations. It then simply just works :)
On my own projects I use RavenDB. At work I use SQL Server and Entity Framework (code first).
So designing domain entities is a challenge, as I really enjoy RavenDB's ability to create an application-centric, DDD style application, that isn't tied at all to a database implementation.
At the moment I'm trying to persist an entity that has a collection of GUIDs that reference other entities in the system. For example (not the actual class, but the same concept):
public class Thing
{
public Thing()
{
this.VisibleSectionIds = new Collection<Guid>();
}
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<Guid> VisibleSectionIds { get; set; }
}
Using RavenDB, I can persist this in a few lines of code with no need to redesign the database. I can even make my collection of ids read-only.
Can people suggest ways that I could do a similar thing in EF without introducing mapping properties to other entities (this would break my DDD approach and possibly introduce N+1 issues). Can I use EF to convert my collection of GUIDs to a text datatype in the database and convert it back again?
I’m putting together a code first model that has a lot of reference data. This model is based around applications, servers, and build deployments. Thus, there are a lot of many to many relationships. The pain that I’m feeling is that new records are being placed in the entity tables which I’m attempting to use as reference data. For example, we have a list of servers. I only want to see a server ONCE in the table. For all the entities referring to that server, I want them to use that row. The same can be said of my ServerRoles and Applications tables. These tables contain static data that I’m seeding and should rarely change.
I know I could solve this with look-ups and hand wiring, but I would think EF would comprehend this scenario.
Using Entity Framework code-first you can create an immutable object with protected parameter less constructor and private set properties.
It works for sure with EF 5 Beta.
[Update]
Tested also with EF 4.3.1, it works.
public class Nation
{
protected Nation() {}
public Nation(Guid id, string name)
{
Id = id;
Name = name;
}
public Guid Id { get; private set; }
public string Name { get; private set; }
}
How to create an entity type and then generate a database table from it?
I know this feature was not supported two years ago in EF, what about now?
You've got 2 options:
Entity Framework Model First where you create the model first and then generate the database from that or
Entity Framework Code First where you create normal Poco objects and generate the database from that.
I've personally used Entity Framework Code First for MVC development and it works like a charm, it really is an awesome feature and easy to use.
Now, Entity Framework introduced these feature.
Basically, with only two steps is sufficient for this, please see below steps to go:
Create your Entity
public class Resturant
{
public int ID { get; set; }
public string Name { get; set; }
}
Create Context class
public class OdeToFoodDb: DbContext
{
public DbSet<Resturant> Resturants { get; set; }
}
However, you may need more coding in Global.ascx for advance options but these are the basic steps.
A database named "OdeToFoodDb" will create and a table named "Resturant" also will create by these steps.