Entity Framework 6 1-1 Navigation Property Always Loads - c#

I Have a Entity Class called Contact:
public class Contact{
public int idContact { get; set; }
public int id_Company { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public bool ShippingLocation { get; set; }
public virtual ICollection<Change> Changes { get; set; }
public virtual ICollection<Entity> Entities { get; set; }
public virtual ICollection<Entity> Entities1 { get; set; }
public virtual Company Company { get; set; }
}
This is all OK. I have LazyLoading enabled in the context.
I wish to find out why, when I retrieve a list of Contacts, the Company property is always filled.
I understand the idea of LazyLoading, and you should specify the navigation properties to load using the Include() extension on the IQueryable (or ensure the Context is still available when accessing the property - otherwise ObjectDisposedException).
I would just like to know why EF is loading the 1-1 automatically, even if I don't specifically ask it to - the side effect of this is I have to now be careful when adding/updating contacts, as I am getting duplicate Company objects in the DB. That is, I have to manually set the Company to null or change its Entity state when updating the related entity.
Edit
This is how I populate the list of contacts:
public Dictionary<int, Contact> GetContacts(Func<T, TKey> selector)
{
using (DbContext db = new Context())
{
return context.Set<Contact>().ToDictionary(selector);
}
}
So, in theory I should get an ObjectDisposedException when I access the Company property, but I don't!

Related

Lazy loading EF Core 2.1 not working with Identity?

I followed the example here
https://learn.microsoft.com/en-us/ef/core/querying/related-data#lazy-loading
And my two classes look like this
public class RefMedSchool
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public string UserFirstName { get; set; }
public string UserLastName { get; set; }
public bool MustChangePassword { get; set; }
public int? MedicalSpecialtyId { get; set; }
[ForeignKey("RefMedicalSpecialtyForeignKey")]
public RefMedicalSpecialty RefMedicalSpecialty { get; set; }
public int RefMedSchoolId { get; set; }
public virtual RefMedSchool RefMedSchool { get; set; }
public UserProfileData UserProfileData { get; set; }
public ICollection<UserFeedback> UserFeedbacks { get; set; }
public ICollection<UserAction> UserActions { get; set; }
public ICollection<UserProgram> UserPrograms { get; set; }
}
But when the database tries to be created I get the error below. Whats wrong ? The properties are virtual as needed.
System.InvalidOperationException: 'Navigation property 'RefMedicalSpecialty' on entity type 'ApplicationUser' is not virtual. UseLazyLoadingProxies requires all entity types to be public, unsealed, have virtual navigation properties, and have a public or protected constructor.'
Entity Framework Core 2.1 introduced lazy loading. It requires all navigation properties to be virtual as explained in the issue Lazy-loading proxies: allow entity types/navigations to be specified:
Currently when lazy-loading proxies are used every entity type in the model must be suitable to proxy and all navigations must be virtual. This issue is about allowing some entity types/navigations to be lazy-loaded while others are not.
The issue is still open and has no resolution, so your desired scenario still isn't supported.
And as the exception tells you:
UseLazyLoadingProxies requires all entity types to be public, unsealed, have virtual navigation properties, and have a public or protected constructor.
So, change all navigation properties (i.e. properties that refer to other entities) to be virtual.
Or use ILazyLoader as explained in Lazy-loading without proxies:
public class Blog
{
private ICollection<Post> _posts;
public Blog()
{
}
private Blog(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
}
private ILazyLoader LazyLoader { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Post> Posts
{
get => LazyLoader?.Load(this, ref _posts);
set => _posts = value;
}
}

Independent child object with references from multiples parents in EF

I'm having quite the issue right now while trying to learn Entity Framework.
Let's say I have this entity:
public class BuildingGroup {
public int ID { get; set; }
public string NameOfManager { get; set; }
public virtual ICollection<Building> Buildings { get; set; }
}
And also this entity.
public class Architect {
public int ID { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public virtual ICollection<Building> BuildingsBeingWorkedOn { get; set; }
}
These two entities are completely unrelated. Here's the Building entity:
public class Building {
public int ID { get; set; }
public string Address { get; set; }
}
My problem happens when I try to add a building to, say a BuildingGroup. In my domain model, I can modify the equivalent collection of buildings, by adding, modifying or removing buildings. However, when I try to update BuildingGroup through a repository, the buildings will not be updated.
public void Update(BuildingGroup buildingGroup) {
var buildingGroupEntity = _context.BuildingGroups.Single(b => b.ID == buildingGroup.ID);
// This will not map the Building collection
context.Entry(buildingGroupEntity).CurrentValues.SetValues(buildingGroup);
// My attempt at mapping the buildings
buildingGroupEntity.Buildings.Clear();
buildingGroup.Buildings.ToList().ForEach(b => buildingGroupEntity.Buildings.Add(_context.Buildings.Single(x => x.ID == b.ID)));
_context.Entry(buildingGroupEntity).State = EntityState.Modified;
}
This fails if the building were not saved in the database prior to the call to Update(), which is normal since buildings can live independently. It must also be done for every child collection of BuildingGroup (if there were more), and for child collections of these children, well...
I have noticed other people use a foreign key constraint in the child object (here, Building), but I can't really do that since many unrelated entities can point to a building: I'd have a lot of navigation properties.
Is there a graceful way to manage referencing objects that can also live independently from those who hold references to them?
If all the entities have to exist independently, yet have relationships with each other, it's better to use many-to-many relationship.
Change your model classes as follows, the Building should contain a couple of collections for architects and groups.
public class BuildingGroup
{
public int ID { get; set; }
public string NameOfManager { get; set; }
public virtual ICollection<Building> Buildings { get; set; }
}
public class Architect
{
public int ID { get; set; }
public string Email { get; set; }
public string Name { get; set; }
public virtual ICollection<Building> BuildingsBeingWorkedOn { get; set; }
}
public class Building
{
public int ID { get; set; }
public string Address { get; set; }
public virtual ICollection<Architect> Architects { get; set; }
public virtual ICollection<BuildingGroup> BuildingGroups { get; set; }
}
If you use entity type configuration, you could define the relationship as follows:
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Building>().HasMany(it => it.Architects).WithMany(it => it.BuildingsBeingWorkedOn);
modelBuilder.Entity<Building>().HasMany(it => it.BuildingGroups).WithMany(it => it.Buildings);
base.OnModelCreating(modelBuilder);
}
}

How should I mark a child entity Inactive instead of deleting from the database but have them behave the same?

I am using Code First and have entities like these:
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
public int ContactId { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
public class Contact
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
When removing a Contact from an Account, I would delete the row from the database. Now instead of deleting the row we update a status column to Inactive. Here I added a Status property to the Contact entity:
public class Contact
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ContactStatus Status {g et; set; }
}
public enum ContactStatus
{
Active = 0,
Inactive = 1
}
Inactive contacts should behave like ones deleted from the database. The user of the website will go to delete the contact and it will 'disappear' like it did before.
Here is our current solution. We create another property called ActiveContacts:
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
public int ContactId { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
[NotMapped]
public ICollection<Contact> ActiveContacts
{
get
{
return Contacts.Where(c => c.Status == Status.Active).ToList();
}
}
}
There are some issues with this. Business logic and linq queries are not aware of the new Status property. I then search all the code for references to the old property, Contacts. Is there a better solution than changing all the references of Contacts to ActiveContacts?
Here is the best thing that I could come up with. Feel free to point out any pitfalls or gotchas that might occur with this approach.
I renamed the navigation property ContactsCollection and used the InversePropertyAttribute to maintain a reference to the raw collection from the database. A Contacts property now returns a list of Contacts with a Status of Active.
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
public int ContactId { get; set; }
[InverseProperty("Contact")]
public virtual ICollection<Contact> ContactsCollection { get; set; }
/// <summary>
/// Represents a list of all Contacts with an Active Status
/// </summary>
[NotMapped]
public ICollection<Contact> Contacts
{
get
{
return ContactsCollection.Where(c => c.Status == Status.Active).ToList();
}
}
}
Now I do not have to search the code base and rename occurrences of Contacts with a property using another name.
I also get compile errors wherever the new get-only Contacts property is attempted to be assigned to or added to. I never assign or add to the collection in a non-compiled razer view. This is working well so far.

Entity Framework properties how does it work

Here are four different approaches to defining an Entity class in Entity Framework. Can someone tell me what is the difference in the way each approach works and also recommend which of these approaches to use?
// Approach 1
public class User
{
public int Id { get; set; }
public Address Address { get; set; }
}
// Approach 2
public class User
{
public int Id { get; set; }
public Address Address { get; set; }
public User()
{
this.Address = new Address();
}
}
// Approach 3
public class User
{
public int Id { get; set; }
public virtual Address Address { get; set; }
}
// Approach 4
public class User
{
public int Id { get; set; }
public virtual Address Address { get; set; }
public User()
{
this.Address = new Address();
}
}
Can I please ask for any good explanation of the differences?
Are the differences related to Lazy loading vs. Eager loading?
Which is better and why?
Here is how it should look like:
public class User
{
public int Id { get; set; }
public int AddressId { get; set; }
public virtual Address Address { get; set; }
}
Explanations:
We need to mark our navigation properties as virtual to enable EF lazy loading at runtime. EF creates a user proxy object inheriting from your user class and marking Address as virtual allows EF to override this property and add lazy loading support code.
Having an AddressId as a FK for Address navigation property essentially converts your User-Address association to a "Foreign Key Association". These type of associations are preferred since they are easier to work with when it comes to updates and modifications.
Unless you have a navigation property in the form of collection of objects (e.g. IList<Address>) you don't need to initialize it in your constructor. EF will do that for you automatically if you include them in your queries.

Many to Many self Join with Entity Framework Code First

Consider this Poco:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
}
Now i want to implement a follow technique where a user may follow other users so basically its self Many to Many relationship
problem is i don't know how exactly i can achieve this in Entity Framework Code-First ?
I thought of a linker Table :
public class UserFollow
{
public int Id { get; set; }
public int Follower { get; set; }
public int Following { get; set; }
public DateTime FollowDate { get; set; }
}
i want to be able to get All Followers and Following from every User Object?
This is quite simple using EF code-first as you only need the User POCO:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
public ICollection<User> FollowedUsers { get; set; }
}
The collection means that a User is related to other users.
PS: I noted you added a timestamp in your solution example. To achieve that you should still add the collection changing the generic type to whatever suits your needs.
Hope it helps.

Categories

Resources