I'm facing some problems working with EF DB First. Say I've got:
A table Person
A table Student with a foreign key pointing to Person
A table Teacher with a foreign key pointing to Person
The model created from the database generates the next classes:
public class Person{
this.Student= new HashSet<Student>();
this.Teacher= new HashSet<Teacher>();
}
public class Student{}
public class Teacher{}
And what I'd really like to see is
public class Person{}
public class Student:Person{}
public class Teacher:Person{}
Is there any convention over configuration or anything I'm missing to get the inherited classes ?
UPDATE
Classes are generated in such a way because the model specifies these associations between Person, Teacher and Student. My question should be then...Is there any way to create a model from a DB using EF so that the model contains classes that inherit from other ones?
You're looking for Table-per-Type (TPT) mapping. Try the solution here:
Entity Framework DB-First, implement inheritance
Related
Given class animal when using Entity Framework:
public class MyDbContext : DbContext
{
public DbSet<animal> abc_animals { get; set; }
}
Does the property name abc_animals matter? I was hoping this would control the table name without having to use annotations but apparently not. It's annoying if I want to prefix all my table-names with the same string.
Source : Here
In past pre-release of EF Core, the table name for an entity was the
same as the entity class name. In RC2 we now use the name of the DbSet
property. If no DbSet property is defined for the given entity type,
then the entity class name is used.
Table Naming Convention Changes
A significant functional change we took in RC2 was to use the name of
the DbSet property for a given entity as the table name it
maps to, rather than just the class name. You can read more about this
change in the related announcement issue.
I am working on a project utilizing MVC4 and EF Data First in VS2012. The table has a primary key which does not have "id" in the field name so EF does not understand it should use it as the primary key. After EF generates the code I add the following annotations and using statements.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public partial class Game
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber { get; set; }
If I base my models from the generate code the custom changes I make will be discard if I update the database models. How can I keep my custom changes and update the database EF data model.
Thanks
use MetadataTypeAttribute (MSDN) to define a metadata class on a partial implementation of your entity class, then decorate the properties in that metadata class.
Note that the decorated partial class implementation should exist in a file other than the autogenerated file so as to persist refreshing from DB.
(question: if your model is DB first, why doesn't it know what the PK is for the Game table? Whether or not the property has Id at the end doesn't matter when it's reading the table schema to generate the model...)
[MetadataType("GameMetadata")]
public partial class Game
{
public class GameMetadata
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int GameNumber;
}
}
Let's say I have 'Customer' table in SQL DB and I'm using Entity Framework.
Now, for instance, in Controller or ViewModel I retrieve the customer by var customer = Page.Current.Customer when it's code is:
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).Customers.First();
}
}
}
My question:
Should I refer to Entity Object class(Customer) as DAL and create CustomerWrapper or I can use it in other code of my application?
I mean, is it correct that Page.Current.Customer will return Customer Entity or I should use Customer Entity as DAL and Page.Current.Customer should return custom Customer, some kind of CustomWrapper?
In one hand if will decided to change Customer table name to site_Customer(in SQL DB) I'll refresh the EntityModel and will only change the code in the Page class to
public class Page
{
...
// Customer is EntityObject that created by Entity Framework
public Customer Customer
{
get
{
return (new ContextEntity()).site_Customers.First();
}
}
}
But in the other hand I'll have Customer Entity + WrapperCustomer
What is better?
All class in an EDMX file are partial classes. This means that you can extend these classes by creating a new Class file.
For example...
public partial class Customer
{
// Here are the methods, properties, relationships created by EDMX Wizard.
}
In another area of your project, I usually put it in the same location as the EDMX, you can add a new Class file that has the same signature.
public partial class Customer
{
// Here are the methods, properties, etc. created by you.
}
When the project is compiled these two classes will become one class in the compiled code. Now, when you change your EDMX, yes it should map correctly, but this is not always the case as EF has be known to be very buggy (suppose to be fixed with EF 4.1 in MVC 3), you can simply change the class name to match whatever it is in the EDMX and "Voila!" you have transferred all custom added code for the class to the new entity object. This is essentially your "class wrapper".
That all depends on the level of abstraction you want to use in your application and needs of presentation layer. Both approaches are possible.
Your code is probably already tightly coupled to Entity Framework (EntityObject is EF type) and it is also not very well testable (Page.Current is probably static) so discussion about some more advanced architecture approaches and separation of concerns is not needed.
Few observations from your code:
Context is Disposable!!!
Renaming anything in your database should not modify your class names. That is the responsibility of EF mapping (EDMX) to correctly map entities to new database names.
If you want to use WCF, then you will probably need to create clear POCOs to avoid a lot of issues.
If you want your controllers/viewmodels/pages/whatever to be unit testable, then you will need to abstract your EntityContext in repository interfaces+classes (see repository pattern).
If you just want to make a quick and simple non-testable application, then you don't need to bother about it. Don't forget to dispose the data context at the end of each request.
I'm having a lot of difficulty with the Entity Model Framework.
I'm just learning how to use this, so please bear with me.
This is the exception, along with the line of code that it gets thrown on:
This is what the model looks like, along with the model that it inherits from
This is what the mapping details looks like: (Top of if statement was cut off)
Here's what AccountContext looks like
If I didn't provide enough information then please let me know
How do I map the "User" Entity?
You have a class hierarchy there and there are three different strategies for inheritance mapping: TPH, TPT and TPC.
As far as I understand in all three strategies you need to include the Base class into you DbContext:
public class AccountContext : DbContext
{
public DbSet<BaseModel> BaseModels { get; set; }
}
This leads automatically to TPH mapping. For the other two strategies you need additional mappings either by data annotations or in Fluent API.
Edit
To query for your derived classes (like User) you can work with the OfType method, for instance:
UserDb.BaseModels.OfType<User>().ToList()
This would return all entities of type User into a list.
I am looking to setup architecture for entity framework that will break apart the entities into multiple models. What I am wondering if it is possible to code-generate one set of entities, so that each model uses the same set of data access classes? I realize the issue with contexts, but I was wondering if each context really needed to have its own set of classes, or I can create many contexts but only have one set of classes that represent the backend tables, using the self-tracking entities generation feature.
Thanks.
You can definitely share POCO classes across multiple models.
For example a class like this:
public class Person
{
public int ID {get;set;}
public string Firstname {get;set;}
public string Surname {get;set;}
public string Lastname {get {return Surname;} set {Surname = value;}}
}
Would work in an EDMX that defines Person as ID,Firstname,Surname
And would work in a second EDMX that defines Person as ID,Firstname,Lastname
Not sure though about Self-Tracking Entities, STEs are 'POCO' but they also have some model specific code which might break if the definition of the EntityType is different in your two EDMXs (like in my above sample).
You'd have to try it out.
Hope this helps
Alex (Former EF team member)