Home > Net >  Entity Framework - Check if navigation property is present
Entity Framework - Check if navigation property is present

Time:04-01

I have this code:

var myAddress = employeeEntity.Organization.OrganizationAddress
.FirstOrDefault(a => a.Address.AddressTypeId).Equals(addressType)

In some cases the Address entity related to OrganizationAddress can be null and this sentence is giving me an error, how can I do it even if the Address entity is null? is there any way that will bring null and not error if the Address is null?

OrganizationAddress is a list because can have many addresses of different type

CodePudding user response:

I found the solution, I didn't know I can specify the Adress as nullable.

var myAddress = employeeEntity.Organization.OrganizationAddress
.FirstOrDefault(a => (bool)(a.Address?.AddressTypeId).Equals(addressType)).Equals(true));

CodePudding user response:

A somewhat odd approach... Firstly using FirstOrDefault with no OrderBy is not advisable as the result will not be guaranteed repeatable if you have more than one organization address.

Overall if you want to see if this organizationaddress (list?) contains a matching address with AddressType you could use

var isMyAddress = employeeEntity.Organization.OrganizationAddress
    .Any(a => a.Address != null 
        && a.Address.AddressTypeId == addressType);

If your check is more that you what to see if the first organization address is that type, then there should be an OrderBy clause to be deterministic as to which OrganizationAddress is the first one. This could be something like a CreatedDate or a SortOrder to identify which one came first:

var isMyAddress = employeeEntity.Organization.OrganizationAddress
    .OrderBy(oa => oa.CreatedDateTime)
    .FirstOrdefault(a => a.Address?.AddressTypeId) == addressType;

This is when dealing with an entity that is already loaded in memory. The problem I see with your approach where Address might be null in a case where lazy loading has been disabled, such as your navigation properties are not declared as virtual or supporting proxy-less lazy loading. The solution you found addresses how to handle a situation where the Address might be Null.. I would take a closer look because I would suspect that in that data structure the Address in an OrgainzationAddress (which looks to be a many-to-many joining table) should never be Null.

If lazy loading is enabled and the Address was not eager loaded but accessed and a matching row exists in the database, EF will have executed a query to retrieve it. This has a performance cost (many round trips to the DB as properties are accessed) but trades off with only loading data if and when it is actually needed. If you don't have lazy loading enabled, then the above code is 100% dependent on either a) you remember to eager load the OrganizationAddress and related Address into your employee entity before calling this code:

var employeeEnitity = _dbContext.Employees
    .Include(e => e.Orgainzation)
        .ThenInclude(o => o.OrganizationAddress)
            .ThenInclude(oa => oa.Address)
    .Where(e => e.EmployeeId == employeeId)
    .Single();

... or b) you are relying on the possibility that EF might already be tracking related entities by the time you read the Employee. This is dangerous because it is completely subjective at runtime and can lead to odd intermittent behaviour where some calls seem to have an Address loaded, while other times no Address is loaded even when one is clearly present in the database. When you don't eager load, and don't have lazy loading enabled, then fetch a top-level entity, EF will still fill in related entities from the pool of entities it is currently tracking. This often results in an incomplete picture of the entity graph and that will vary depending on how many related entities the DbContext might happen to be tracking at the time.

  • Related