I have the following entity I’m trying to get to work with EF Core/NET7, where two properties map to the same column. This way either property could be used in various interfaces without breaking old code.
Any way to make this work in EF Core?
public class AppUser
{
public int Id { get; internal set; }
public string Name { get => UserName; set => UserName = value; }
public string UserName { get; set; }
}
. . .
var item = context.Set<AppUser>().FirstOrDefault(x => x.Name == “admin”).ToList();
. . .
builder.Property(x => x.UserName)
.HasColumnName(“UserName”);
builder.Ignore(x => x.Name);
// or
builder.Property(x => x.Name)
.HasColumnName(“UserName”)
.ValueGeneratedOnAddOrUpdate();
Or is there a way of making the Name property project to UserName, similar to how AutoMapper projections map DTO fields with IQueryable extensions?
The AppUser
class is actually derived from IdentityUser<int>
, so the idea is to use the class with both the ASP.NET Core Identity framework AND internal classes that require a INameEntity
type. Updated definitions are below.
Also, I tried using builder.Property(u => u.Name).HasColumnName("UserName").ValueGeneratedOnAddOrUpdate()
as mentioned here, but it throws the exception Invalid column name 'UserName1'.
If it helps, I'm using NET7.
public interface INameEntity
{
int Id { get; }
string Name { get; }
}
public class AppUser : IdentityUser<int>, IEquatable<AppUser>, INameEntity
{
public int Id { get; internal set; }
public string Name { get => UserName; set => UserName = value; }
public string UserName { get; set; }
}
public class AppUserConfig : IEntityTypeConfiguration<AppUser>
{
public void Configure(EntityTypeBuilder<AppUser> builder)
{
. . .
builder.Property(u => u.UserName)
.HasColumnName(“UserName”)
.HasMaxLength(ModelConfig.MaxUserNameLen)
.IsRequired();
builder.Ignore(u => u.Name);
. . .
}
}
You can use this my extension EFCoreLinqExtensions for replacing AppUser.Name
property to AppUser.UserName
in LINQ query.
Usage is simple:
public class AppDbContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
// We add AppUser.Name property replacement to use AppUser.UserName.
optionsBuilder.UseMemberReplacement((AppUser u) => u.Name,
u => u.UserName);
}
}
Extension should automatically correct LINQ query to be translatable.