dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.79k stars 3.19k forks source link

Support or not to NotMapped Property Map to Entity Property #35071

Open jinzaz opened 3 days ago

jinzaz commented 3 days ago

I have a requirement that defines an attribute in the abstract class, and the derived class can specify an attribute mapped to the derived class. The reason for this requirement is that all derived classes have an attribute with the same meaning but different attribute names. I want to implement a common query or modification method in this way

I want the code implemented

Entity definition:

public abstract class EntityBase
{
      public Guid Id { get; set; }

      [NotMapped]
      public abstract string? Name { get; set; }
}

public class EntityA : EntityBase
{
     public string? NormalName { get; set; }

     public override string? Name
     {
           get => NormalName ;
           set => NormalName  = value;
     }
}

public class EntityB: EntityBase
{
     public string? DefaultName { get; set; }

     public override string? Name
     {
           get => DefaultName ;
           set => DefaultName   = value;
     }
}

The effect want to achieve:

public async Task RunAsync<TEntity> (string name) where TEntity : EntityBase
{
       var entity = db.Set<TEntity>().Where(x => x.Name == name).FirstOrDefaultAsync();

       var effective= db.Set<TEntity>().Where(x => x.Name == name).ExecuteUpdateAsync(e => e.SetProperty(s => s.Name, s => name))();
}

That doesn't seem to be supported at the moment, which way can I use to achieve this effect ?

roji commented 2 days ago

It's not completely clear what exact database mapping you're looking for, and what inheritance strategy you're using (TPH, TPT, TPC) - what columns exactly are you looking to see in the database?

The quickest thing that comes to mind is to invert your config: map the Name property, which is inherited and can be mapped to a single column for all type in the hierarchy, and add [NotMapped] to your inherited/specific property names (NormalName/DefaultName). This way, your .NET code can interact with NormalName/DefaultName - which would internally read and write from Name - but EF would only access Name. You can even decide to make Name private so that it isn't visible to .NET code.

Otherwise, please provide more detail on exactly what you're trying to achieve.

jinzaz commented 1 day ago

The effect I want is that NormalName and DefaultName are fields that already exist in the database, and I want to use Name to uniformly query or modify the corresponding NormalName or DefaultName

roji commented 1 day ago

OK, in other words, the request here is to map a property in a single CLR property in a hierarchy to different columns for different entity types in the hierarchy. @AndriySvyryd you probably have the answer ready...

ajcvickers commented 1 day ago

@jinzaz It is possible to map a property to different column names in different tables when using TPC or TPT inheritance mapping. See Properties mapped to different column names. This should allow mapping Name in the CLR type to the NormalName and DefaultName columns. However, this doesn't allow mapping NormalName and DefaultName properties in the CLR type.

jinzaz commented 14 hours ago

@jinzaz It is possible to map a property to different column names in different tables when using TPC or TPT inheritance mapping. See Properties mapped to different column names. This should allow mapping Name in the CLR type to the NormalName and DefaultName columns. However, this doesn't allow mapping NormalName and DefaultName properties in the CLR type.

This seems to be what I want, I tried it, not sure if TPH supports it