Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core non-primitive type value object as primary key?

I've been trying to use a value object as a unique id in entity framework core. I've gotten to the point where it is saving to the database correctly, but EF is not querying the database correctly to find my entity. It looks like EF is loading the whole table, then doing the mapping in memory. When I look at the query it does not include a predicate for the id.

I'm dealing with an existing database that uses 10 character string ids with padded zeros so I'm seeing if working with them as value objects is going to work. My next thing to try is just use a Guid and have the 'SalesOrderNumber' as a separate field. That's just for this case though, what I'm really trying to figure out is if it is possible to use a value object as an primary key in entity framework.

Entity:

public class SalesOrder: Entity<SalesOrderNumber>
    {
        private SalesOrder() { }

        public SalesOrder(SalesOrderNumber id, DateTime dueDate)
        {
            Id = id;
            DueDate = dueDate;
            Open = true;
        }

        public override SalesOrderNumber Id { get; protected set; }
        public DateTime DueDate { get; private set; }
        public bool Open { get; private set; }
    }

Value Object:

  public class SalesOrderNumber: ValueObject
    {
        private readonly string _salesOrderNumber;

        public SalesOrderNumber(string salesOrderNumber)
        {
            if (string.IsNullOrWhiteSpace(salesOrderNumber) || salesOrderNumber.Length > 10)
                throw new InvalidOperationException($"Sales Order Number  {salesOrderNumber} is invalid");

            _salesOrderNumber= salesOrderNumber;
        }

        protected override IEnumerable<object> GetAtomicValues()
        {
            yield return _salesOrderNumber;
        }

        public override string ToString() => _salesOrderNumber;
    }

DB Config:

public void Configure(EntityTypeBuilder<SalesOrder> builder)
        {
            builder.HasKey(e => e.Id);
            builder.Property(e => e.Id).HasConversion(number => number.ToString(), s => new SalesOrderNumber(s));

        }

I've reviewed some other SO posts but none of them have addressed the query issue I've run into: EF Core / DbContext > Map custom type as primary key

like image 241
ErpaDerp Avatar asked Nov 15 '18 21:11

ErpaDerp


1 Answers

The performance problem you laid out seems to be an open issue reported on github: EF Core non-primitive type value object as primary key?

Someone also reported a quick fix: https://github.com/aspnet/EntityFrameworkCore/issues/13669#issuecomment-439589393 If I understood the quick fix right, adding implicit conversion operator from the value object to the backing primitive type, and an implicit conversion operator for the backward direction, may resolve your issue. Please leave a comment if this works for you.

like image 161
Hermann.Gruber Avatar answered Oct 13 '22 20:10

Hermann.Gruber