Base solution for your next web application
Open Closed

Best Way To Create Calculated Property in Model for EF CORE #3070


User avatar
0
cangunaydin created

Hello, My question is related with the model. When i was using ef 6 i was using Microsoft.Linq.Translations package to filter and create calculated properties inside the model. With the help of this library i could create where queries to filter. As an example.

I have Associate, Company and Person model.

Person has FirstName and LastName
Company has only the Name Property and Associate has Type property which holds the information if it is a person or company

sth like this.

Associate

public class Associate : FullAuditedEntity, IMayHaveTenant
    {
        
        public int? TenantId { get; set; }

        public AssociateType Type { get; set; }

        private static readonly CompiledExpression<Associate, string> NameExpression
                    = DefaultTranslationOf<Associate>.Property(a => a.Name).Is(a => a.Type == AssociateType.Person ? a.Person.FirstName + " "+ a.Person.LastName : a.Company.Name);

        private static readonly CompiledExpression<Associate, string> EmailExpression
                   = DefaultTranslationOf<Associate>.Property(a => a.Email).Is(a => a.Type == AssociateType.Person ? a.Person.Email : a.Company.Email);
        
        public string Name
        {
            get
            {

                return NameExpression.Evaluate(this);

            }
        }

        public string Email
        {
            get
            {
                return EmailExpression.Evaluate(this);
            }
        }

        public virtual Person Person { get; set; }
        public virtual Company Company { get; set; }



    }

As you can see readonly properties are not created in db but i can do the filtering and sorting through iqueryable. I was achieving this with the help of the library but now with the update ef core doesn't support it. Do you have any idea how can i achieve the same behavior with ef core. Thanks in advance.


3 Answer(s)
  • User Avatar
    0
    cangunaydin created

    Also i want to ask sth else related. when i try to get the entity with an id for the associate, it does not get the model person or company which is lazy loaded normally in ef6. Now when i call getasync method i can not load the other models in an easy way so instead in my app service i coded like this.

    public async Task<GetAssociateForEditOutput> GetAssociateForEdit(NullableIdDto input)
            {
                Associate associate = null;
                if (input.Id.HasValue)
                {
                    associate = await _associateRepository.GetAll().Include(a => a.Person).Include(a => a.Company).Where(a => a.Id == input.Id.Value).FirstOrDefaultAsync();
                }
    
                var output = new GetAssociateForEditOutput();
    
                //Associate
                output.Associate = associate != null
                    ? associate.MapTo<AssociateEditDto>()
                    : new AssociateEditDto() { Person = new AssociateEditPerson(), Company = new AssociateEditCompany() };
    
    
                return output;
            }
    
       is there an easy extension to load this child models with getasync ?
    

    this was my previous code.

    public async Task<GetAssociateForEditOutput> GetAssociateForEdit(NullableIdDto input)
            {
                Associate associate = null;
                if (input.Id.HasValue)
                {
                    associate = await _associateRepository.GetAsync(input.Id.Value);
                }
    
                var output = new GetAssociateForEditOutput();
    
                //Associate
                output.Associate = associate != null
                    ? associate.MapTo<AssociateEditDto>()
                    : new AssociateEditDto() { Person = new AssociateEditPerson(), Company = new AssociateEditCompany() };
    
    
                return output;
            }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    For your first question, have you tried ignoring that field in your DbContext's onModelCreating ?

    modelBuilder.Entity<MyEntity>().Ignore(e => e.NotMappedProperty);
    

    For your second question, EF Core does not support lazy loading at the moment. Instead, you can use EnsureLoadedAsync of generic repositories like this:

    await _personRepository.EnsureLoadedAsync(person, p => p.Phones);
    

    Thanks.

  • User Avatar
    0
    cangunaydin created

    Hello @ismcagdas For the first answer. Yes i have tried it but you can only select it. You can not do filtering and sorting. My quick fix for that is i am relating the properties to db and everytime i create or update i am also rewriting the values to the parent associate table.

    For the second answer. EnsureLoadedAsync doesn't support only one entity it expects icollection or ienumerable i guess. for my example i can not use it.