I have some POCO classes which can generally divided into two groups, for example:
public class Student
{
public Student()
{
this.Courses = new List<Course>();
this.Clubs = new List<Club>();
}
public int Id { get; set; }
public virtual ICollection<Course> Courses { get; set; }
public virtual ICollection<Club> Clubs { get; set; }
}
and corresponding Course and Club classes, and they all have their own relationships to other classes.
The problem is, those two groups are big, they both contains a lot of classes, and each of them is a working unit, like student courses management unit which will provide functions for anything related to course; and club management unit which will provide functions. So I am not planning to put them together into one DbContext.
There are some requirements that will need to get a student from club then retrieve its course information. What I am doing now, is do another query in course unit by using the student Id I got from club unit. Which works fine but I hopping to make it simpler, like
foreach(var student in club.Students){
ClubContext.Detach(student);
CourseContext.Attach(student);
foreach(var c in student.Courses){
...
}
}
but I got some exception like this:
There is already a generated proxy type for the object layer type
'POCOTest.Models.Student'. This occurs when the same object layer
type is mapped by two or more different models in an AppDomain.
Is this possible? and if so, how? Thanks~
You can have single class mapped in multiple contexts but the mapping should be always the same. If it is not the same you cannot use dynamic proxies (lazy loading) because each mapping demands its own proxy type handling its navigation properties.
In your case the first context mapping contains Student entity with relation to Club but this relation doesn't exist in the second mapping where in contrary relation with Course exists. That demands two different proxy types for the same entity type.
The exception says that it is not supported. There are two reasons why this cannot work:
EF stores proxy types in static dictionary where each entity type can have only single generated proxy
Even if you fix the first point (by downloading source codes and modifying them) you will still not be able to do what you want because proxy type is the entity. It is not a wrapper. So the type cannot be replaced when you detach it from the first context and attach to second one.
If you don't need lazy loading, just remove the "virtual" keyword from your navigation properties and it will work as you want. Virtual is used to enable Lazy Loading.
Related
I had seen some books(e.g programming entity framework code first Julia Lerman) define their domain classes (POCO) with no initialization of the navigation properties like:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Address { get; set; }
public virtual License License { get; set; }
}
some other books or tools (e.g Entity Framework Power Tools) when generates POCOs initializes the navigation properties of the the class, like:
public class User
{
public User()
{
this.Addresses = new IList<Address>();
this.License = new License();
}
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual License License { get; set; }
}
Q1: Which one is better? why? Pros and Cons?
Edit:
public class License
{
public License()
{
this.User = new User();
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
Q2: In second approach there would be stack overflow if the `License` class has a reference to `User` class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
Collections: It doesn't matter.
There is a distinct difference between collections and references as navigation properties. A reference is an entity. A collections contains entities. This means that initializing a collection is meaningless in terms of business logic: it does not define an association between entities. Setting a reference does.
So it's purely a matter of preference whether or not, or how, you initialize embedded lists.
As for the "how", some people prefer lazy initialization:
private ICollection<Address> _addresses;
public virtual ICollection<Address> Addresses
{
get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}
It prevents null reference exceptions, so it facilitates unit testing and manipulating the collection, but it also prevents unnecessary initialization. The latter may make a difference when a class has relatively many collections. The downside is that it takes relatively much plumbing, esp. when compared to auto properties without initialization. Also, the advent of the null-propagation operator in C# has made it less urgent to initialize collection properties.
...unless explicit loading is applied
The only thing is that initializing collections makes it hard to check whether or not a collection was loaded by Entity Framework. If a collection is initialized, a statement like...
var users = context.Users.ToList();
...will create User objects having empty, not-null Addresses collections (lazy loading aside). Checking whether the collection is loaded requires code like...
var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;
If the collection is not initialized a simple null check will do. So when selective explicit loading is an important part of your coding practice, i.e. ...
if (/*check collection isn't loaded*/)
context.Entry(user).Collection(c => c.Addresses).Load();
...it may be more convenient not to initialize collection properties.
Reference properties: Don't
Reference properties are entities, so assigning an empty object to them is meaningful.
Worse, if you initiate them in the constructor, EF won't overwrite them when materializing your object or by lazy loading. They will always have their initial values until you actively replace them. Worse still, you may even end up saving empty entities in the database!
And there's another effect: relationship fixup won't occcur. Relationship fixup is the process by which EF connects all entities in the context by their navigation properties. When a User and a Licence are loaded separately, still User.License will be populated and vice versa. Unless of course, if License was initialized in the constructor. This is also true for 1:n associations. If Address would initialize a User in its constructor, User.Addresses would not be populated!
Entity Framework core
Relationship fixup in Entity Framework core (2.1 at the time of writing) isn't affected by initialized reference navigation properties in constructors. That is, when users and addresses are pulled from the database separately, the navigation properties are populated.
However, lazy loading does not overwrite initialized reference navigation properties.
In EF-core 3, initializing a reference navigation property prevents Include from working properly.
So, in conclusion, also in EF-core, initializing reference navigation properties in constructors may cause trouble. Don't do it. It doesn't make sense anyway.
In all my projects I follow the rule - "Collections should not be null. They are either empty or have values."
First example is possible to have when creation of these entities is responsibility of third-part code (e.g. ORM) and you are working on a short-time project.
Second example is better, since
you are sure that entity has all properties set
you avoid silly NullReferenceException
you make consumers of your code happier
People, who practice Domain-Driven Design, expose collections as read-only and avoid setters on them. (see What is the best practice for readonly lists in NHibernate)
Q1: Which one is better? why? Pros and Cons?
It is better to expose not-null colections since you avoid additional checks in your code (e.g. Addresses). It is a good contract to have in your codebase. But it os OK for me to expose nullable reference to single entity (e.g. License)
Q2: In second approach there would be stack overflow if the License class has a reference to User class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
When I developed data mapper pattern by myself I tryed to avoid bidirectional references and had reference from child to parent very rarely.
When I use ORMs it is easy to have bidirectional references.
When it is needed to build test-entity for my unit-tests with bidirectional reference set I follow the following steps:
I build parent entity with emty children collection.
Then I add evey child with reference to parent entity into children collection.
Insted of having parameterless constructor in License type I would make user property required.
public class License
{
public License(User user)
{
this.User = user;
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
It's redundant to new the list, since your POCO is depending on Lazy Loading.
Lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed. When using POCO entity types, lazy loading is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook.
If you would remove the virtual modifier, then you would turn off lazy loading, and in that case your code no longer would work (because nothing would initialize the list).
Note that Lazy Loading is a feature supported by entity framework, if you create the class outside the context of a DbContext, then the depending code would obviously suffer from a NullReferenceException
HTH
The other answers fully answer the question, but I'd like to add something since this question is still relevant and comes up in google searches.
When you use the "code first model from database" wizard in Visual Studio all collections are initialized like so:
public partial class SomeEntity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public SomeEntity()
{
OtherEntities = new HashSet<OtherEntity>();
}
public int Id { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<OtherEntity> OtherEntities { get; set; }
}
I tend to take wizard output as basically being an official recommendation from Microsoft, hence why I'm adding to this five-year-old question. Therefore, I'd initialize all collections as HashSets.
And personally, I think it'd be pretty slick to tweak the above to take advantage of C# 6.0's auto-property initializers:
public virtual ICollection<OtherEntity> OtherEntities { get; set; } = new HashSet<OtherEntity>();
Q1: Which one is better? why? Pros and Cons?
The second variant when virtual properties are set inside an entity constructor has a definite problem which is called "Virtual member call in a constructor".
As for the first variant with no initialization of navigation properties, there are 2 situations depending on who / what creates an object:
Entity framework creates an object
Code consumer creates an object
The first variant is perfectly valid when Entity Framework creates a object,
but can fail when a code consumer creates an object.
The solution to ensure a code consumer always creates a valid object is to use a static factory method:
Make default constructor protected. Entity Framework is fine to work with protected constructors.
Add a static factory method that creates an empty object, e.g. a User object, sets all properties, e.g. Addresses and License, after creation and returns a fully constructed User object
This way Entity Framework uses a protected default constructor to create a valid object from data obtained from some data source and code consumer uses a static factory method to create a valid object.
I use the answer from this Why is my Entity Framework Code First proxy collection null and why can't I set it?
Had problems with constructor initilization. Only reason I do this is to make test code easier. Making sure collection is never null saves me constantly initialising in tests etc
I had seen some books(e.g programming entity framework code first Julia Lerman) define their domain classes (POCO) with no initialization of the navigation properties like:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Address { get; set; }
public virtual License License { get; set; }
}
some other books or tools (e.g Entity Framework Power Tools) when generates POCOs initializes the navigation properties of the the class, like:
public class User
{
public User()
{
this.Addresses = new IList<Address>();
this.License = new License();
}
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual License License { get; set; }
}
Q1: Which one is better? why? Pros and Cons?
Edit:
public class License
{
public License()
{
this.User = new User();
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
Q2: In second approach there would be stack overflow if the `License` class has a reference to `User` class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
Collections: It doesn't matter.
There is a distinct difference between collections and references as navigation properties. A reference is an entity. A collections contains entities. This means that initializing a collection is meaningless in terms of business logic: it does not define an association between entities. Setting a reference does.
So it's purely a matter of preference whether or not, or how, you initialize embedded lists.
As for the "how", some people prefer lazy initialization:
private ICollection<Address> _addresses;
public virtual ICollection<Address> Addresses
{
get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}
It prevents null reference exceptions, so it facilitates unit testing and manipulating the collection, but it also prevents unnecessary initialization. The latter may make a difference when a class has relatively many collections. The downside is that it takes relatively much plumbing, esp. when compared to auto properties without initialization. Also, the advent of the null-propagation operator in C# has made it less urgent to initialize collection properties.
...unless explicit loading is applied
The only thing is that initializing collections makes it hard to check whether or not a collection was loaded by Entity Framework. If a collection is initialized, a statement like...
var users = context.Users.ToList();
...will create User objects having empty, not-null Addresses collections (lazy loading aside). Checking whether the collection is loaded requires code like...
var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;
If the collection is not initialized a simple null check will do. So when selective explicit loading is an important part of your coding practice, i.e. ...
if (/*check collection isn't loaded*/)
context.Entry(user).Collection(c => c.Addresses).Load();
...it may be more convenient not to initialize collection properties.
Reference properties: Don't
Reference properties are entities, so assigning an empty object to them is meaningful.
Worse, if you initiate them in the constructor, EF won't overwrite them when materializing your object or by lazy loading. They will always have their initial values until you actively replace them. Worse still, you may even end up saving empty entities in the database!
And there's another effect: relationship fixup won't occcur. Relationship fixup is the process by which EF connects all entities in the context by their navigation properties. When a User and a Licence are loaded separately, still User.License will be populated and vice versa. Unless of course, if License was initialized in the constructor. This is also true for 1:n associations. If Address would initialize a User in its constructor, User.Addresses would not be populated!
Entity Framework core
Relationship fixup in Entity Framework core (2.1 at the time of writing) isn't affected by initialized reference navigation properties in constructors. That is, when users and addresses are pulled from the database separately, the navigation properties are populated.
However, lazy loading does not overwrite initialized reference navigation properties.
In EF-core 3, initializing a reference navigation property prevents Include from working properly.
So, in conclusion, also in EF-core, initializing reference navigation properties in constructors may cause trouble. Don't do it. It doesn't make sense anyway.
In all my projects I follow the rule - "Collections should not be null. They are either empty or have values."
First example is possible to have when creation of these entities is responsibility of third-part code (e.g. ORM) and you are working on a short-time project.
Second example is better, since
you are sure that entity has all properties set
you avoid silly NullReferenceException
you make consumers of your code happier
People, who practice Domain-Driven Design, expose collections as read-only and avoid setters on them. (see What is the best practice for readonly lists in NHibernate)
Q1: Which one is better? why? Pros and Cons?
It is better to expose not-null colections since you avoid additional checks in your code (e.g. Addresses). It is a good contract to have in your codebase. But it os OK for me to expose nullable reference to single entity (e.g. License)
Q2: In second approach there would be stack overflow if the License class has a reference to User class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
When I developed data mapper pattern by myself I tryed to avoid bidirectional references and had reference from child to parent very rarely.
When I use ORMs it is easy to have bidirectional references.
When it is needed to build test-entity for my unit-tests with bidirectional reference set I follow the following steps:
I build parent entity with emty children collection.
Then I add evey child with reference to parent entity into children collection.
Insted of having parameterless constructor in License type I would make user property required.
public class License
{
public License(User user)
{
this.User = user;
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
It's redundant to new the list, since your POCO is depending on Lazy Loading.
Lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed. When using POCO entity types, lazy loading is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook.
If you would remove the virtual modifier, then you would turn off lazy loading, and in that case your code no longer would work (because nothing would initialize the list).
Note that Lazy Loading is a feature supported by entity framework, if you create the class outside the context of a DbContext, then the depending code would obviously suffer from a NullReferenceException
HTH
The other answers fully answer the question, but I'd like to add something since this question is still relevant and comes up in google searches.
When you use the "code first model from database" wizard in Visual Studio all collections are initialized like so:
public partial class SomeEntity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public SomeEntity()
{
OtherEntities = new HashSet<OtherEntity>();
}
public int Id { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<OtherEntity> OtherEntities { get; set; }
}
I tend to take wizard output as basically being an official recommendation from Microsoft, hence why I'm adding to this five-year-old question. Therefore, I'd initialize all collections as HashSets.
And personally, I think it'd be pretty slick to tweak the above to take advantage of C# 6.0's auto-property initializers:
public virtual ICollection<OtherEntity> OtherEntities { get; set; } = new HashSet<OtherEntity>();
Q1: Which one is better? why? Pros and Cons?
The second variant when virtual properties are set inside an entity constructor has a definite problem which is called "Virtual member call in a constructor".
As for the first variant with no initialization of navigation properties, there are 2 situations depending on who / what creates an object:
Entity framework creates an object
Code consumer creates an object
The first variant is perfectly valid when Entity Framework creates a object,
but can fail when a code consumer creates an object.
The solution to ensure a code consumer always creates a valid object is to use a static factory method:
Make default constructor protected. Entity Framework is fine to work with protected constructors.
Add a static factory method that creates an empty object, e.g. a User object, sets all properties, e.g. Addresses and License, after creation and returns a fully constructed User object
This way Entity Framework uses a protected default constructor to create a valid object from data obtained from some data source and code consumer uses a static factory method to create a valid object.
I use the answer from this Why is my Entity Framework Code First proxy collection null and why can't I set it?
Had problems with constructor initilization. Only reason I do this is to make test code easier. Making sure collection is never null saves me constantly initialising in tests etc
While using Entity Framework Core with SQL Server I encountered an unexpected problem. I have an entity A that has a one-to-many relationship on entity B.
[Table("client")]
public class Client
{
public long ID { get; set; }
public string Name { get; set; }
public ICollection<Configuration> Configurations { get; set; } = new LinkedList<Configuration>();
}
I get a list of instances of entity A from the database like this:
public ICollection<Client> GetAllClients()
{
return _dbContext.Clients.ToList();
}
When I call this function I get a list of instances without the instances of entity B in the relationship. Why are the objects in the relationship not retrieved correctly?
I've also found out that if I add this line of code to the function the entities are retrieved as expected.
public ICollection<Client> GetAllClients()
{
var test = _dbContext.Configurations.ToList();
return _dbContext.Clients.ToList();
}
This makes no sense to me. What am I missing here?
You can use the Include method to specify related data to be included in query results (Eager loading).
Take a look in the following example:
public ICollection<Client> GetAllClients()
{
return _dbContext.Clients.Include(x => x.Configurations).ToList();
}
You can check the MSDN reference.
Related reference/collection properties must either be eagerly or explictly loaded. You generally want to eagerly load using Include:
var clients = await _context.Clients.Include(x => x.Configurations).ToListAsync();
Alternatively, you can lazy load, but that's generally a bad idea, as it can lead to N+1 query problems (i.e. you issue one query, and then a separate additional query for each item as you iterate through, which is obviously highly inefficient). Regardless, lazy loading requires two things:
The reference/collection property must have the virtual keyword. EF adds lazy loading functionality by creating a dynamic proxy of your entity class and overriding the property getter. Overriding, of course, can only be done on virtuals.
You have to explicitly add the lazy-loading services:
services.AddDbContext<MyContext>(o => o.UseLazyLoadingProxies()
.UseSqlServer(connectionString));
It works when you query the configurations as well, because EF has object-fixup. In other words, it will automatically fill related reference/collection properties, if it has previously retrieved those objects already and has them in its object cache. Otherwise, and if you do not otherwise load the relations, the property will remain null.
I had seen some books(e.g programming entity framework code first Julia Lerman) define their domain classes (POCO) with no initialization of the navigation properties like:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Address { get; set; }
public virtual License License { get; set; }
}
some other books or tools (e.g Entity Framework Power Tools) when generates POCOs initializes the navigation properties of the the class, like:
public class User
{
public User()
{
this.Addresses = new IList<Address>();
this.License = new License();
}
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual License License { get; set; }
}
Q1: Which one is better? why? Pros and Cons?
Edit:
public class License
{
public License()
{
this.User = new User();
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
Q2: In second approach there would be stack overflow if the `License` class has a reference to `User` class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
Collections: It doesn't matter.
There is a distinct difference between collections and references as navigation properties. A reference is an entity. A collections contains entities. This means that initializing a collection is meaningless in terms of business logic: it does not define an association between entities. Setting a reference does.
So it's purely a matter of preference whether or not, or how, you initialize embedded lists.
As for the "how", some people prefer lazy initialization:
private ICollection<Address> _addresses;
public virtual ICollection<Address> Addresses
{
get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}
It prevents null reference exceptions, so it facilitates unit testing and manipulating the collection, but it also prevents unnecessary initialization. The latter may make a difference when a class has relatively many collections. The downside is that it takes relatively much plumbing, esp. when compared to auto properties without initialization. Also, the advent of the null-propagation operator in C# has made it less urgent to initialize collection properties.
...unless explicit loading is applied
The only thing is that initializing collections makes it hard to check whether or not a collection was loaded by Entity Framework. If a collection is initialized, a statement like...
var users = context.Users.ToList();
...will create User objects having empty, not-null Addresses collections (lazy loading aside). Checking whether the collection is loaded requires code like...
var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;
If the collection is not initialized a simple null check will do. So when selective explicit loading is an important part of your coding practice, i.e. ...
if (/*check collection isn't loaded*/)
context.Entry(user).Collection(c => c.Addresses).Load();
...it may be more convenient not to initialize collection properties.
Reference properties: Don't
Reference properties are entities, so assigning an empty object to them is meaningful.
Worse, if you initiate them in the constructor, EF won't overwrite them when materializing your object or by lazy loading. They will always have their initial values until you actively replace them. Worse still, you may even end up saving empty entities in the database!
And there's another effect: relationship fixup won't occcur. Relationship fixup is the process by which EF connects all entities in the context by their navigation properties. When a User and a Licence are loaded separately, still User.License will be populated and vice versa. Unless of course, if License was initialized in the constructor. This is also true for 1:n associations. If Address would initialize a User in its constructor, User.Addresses would not be populated!
Entity Framework core
Relationship fixup in Entity Framework core (2.1 at the time of writing) isn't affected by initialized reference navigation properties in constructors. That is, when users and addresses are pulled from the database separately, the navigation properties are populated.
However, lazy loading does not overwrite initialized reference navigation properties.
In EF-core 3, initializing a reference navigation property prevents Include from working properly.
So, in conclusion, also in EF-core, initializing reference navigation properties in constructors may cause trouble. Don't do it. It doesn't make sense anyway.
In all my projects I follow the rule - "Collections should not be null. They are either empty or have values."
First example is possible to have when creation of these entities is responsibility of third-part code (e.g. ORM) and you are working on a short-time project.
Second example is better, since
you are sure that entity has all properties set
you avoid silly NullReferenceException
you make consumers of your code happier
People, who practice Domain-Driven Design, expose collections as read-only and avoid setters on them. (see What is the best practice for readonly lists in NHibernate)
Q1: Which one is better? why? Pros and Cons?
It is better to expose not-null colections since you avoid additional checks in your code (e.g. Addresses). It is a good contract to have in your codebase. But it os OK for me to expose nullable reference to single entity (e.g. License)
Q2: In second approach there would be stack overflow if the License class has a reference to User class too. It means we should have one-way reference.(?) How we should decide which one of the navigation properties should be removed?
When I developed data mapper pattern by myself I tryed to avoid bidirectional references and had reference from child to parent very rarely.
When I use ORMs it is easy to have bidirectional references.
When it is needed to build test-entity for my unit-tests with bidirectional reference set I follow the following steps:
I build parent entity with emty children collection.
Then I add evey child with reference to parent entity into children collection.
Insted of having parameterless constructor in License type I would make user property required.
public class License
{
public License(User user)
{
this.User = user;
}
public int Id { get; set; }
public string Key { get; set; }
public DateTime Expirtion { get; set; }
public virtual User User { get; set; }
}
It's redundant to new the list, since your POCO is depending on Lazy Loading.
Lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed. When using POCO entity types, lazy loading is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook.
If you would remove the virtual modifier, then you would turn off lazy loading, and in that case your code no longer would work (because nothing would initialize the list).
Note that Lazy Loading is a feature supported by entity framework, if you create the class outside the context of a DbContext, then the depending code would obviously suffer from a NullReferenceException
HTH
The other answers fully answer the question, but I'd like to add something since this question is still relevant and comes up in google searches.
When you use the "code first model from database" wizard in Visual Studio all collections are initialized like so:
public partial class SomeEntity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public SomeEntity()
{
OtherEntities = new HashSet<OtherEntity>();
}
public int Id { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<OtherEntity> OtherEntities { get; set; }
}
I tend to take wizard output as basically being an official recommendation from Microsoft, hence why I'm adding to this five-year-old question. Therefore, I'd initialize all collections as HashSets.
And personally, I think it'd be pretty slick to tweak the above to take advantage of C# 6.0's auto-property initializers:
public virtual ICollection<OtherEntity> OtherEntities { get; set; } = new HashSet<OtherEntity>();
Q1: Which one is better? why? Pros and Cons?
The second variant when virtual properties are set inside an entity constructor has a definite problem which is called "Virtual member call in a constructor".
As for the first variant with no initialization of navigation properties, there are 2 situations depending on who / what creates an object:
Entity framework creates an object
Code consumer creates an object
The first variant is perfectly valid when Entity Framework creates a object,
but can fail when a code consumer creates an object.
The solution to ensure a code consumer always creates a valid object is to use a static factory method:
Make default constructor protected. Entity Framework is fine to work with protected constructors.
Add a static factory method that creates an empty object, e.g. a User object, sets all properties, e.g. Addresses and License, after creation and returns a fully constructed User object
This way Entity Framework uses a protected default constructor to create a valid object from data obtained from some data source and code consumer uses a static factory method to create a valid object.
I use the answer from this Why is my Entity Framework Code First proxy collection null and why can't I set it?
Had problems with constructor initilization. Only reason I do this is to make test code easier. Making sure collection is never null saves me constantly initialising in tests etc
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)