Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF4.1 Code First Complex Type as primary key

I'm currently trying to implement the repositories for my domain objects with the RC of Entity Framework 4.1 and its code first approach. Now I have a domain entity "Voyage" which has a unique identifier encapsulated in the type "VoyageNumber"

public class VoyageNumber
{
    private readonly string number;

    public VoyageNumber(string number)
    {
        Validate.NotNull(number, "VoyageNumber is required");

        this.number = number;
    }

    public string Id
    {
        get { return number; }
    }

Now I get an exception when i do this in the configuration of my DbContext:

modelBuilder.Entity<Voyage>().HasKey<VoyageNumber>(k => k.VoyageNumber);

The property 'VoyageNumber' cannot be used as a key property on the entity 'Domain.Model.Voyages.Voyage' because the property type is not a valid key type. Only scalar types, string and byte[] are supported key types.

and also when I try this:

modelBuilder.Entity<Voyage>().HasKey<string>(k => k.VoyageNumber.Id);

The properties expression 'k => k.VoyageNumber.Id' is not valid. The expression should represent a property: C#: 't => t.MyProperty'

Do I really have to trash my VoyageNumber and replace it with a primitive type?

like image 352
hoetz Avatar asked Apr 02 '11 10:04

hoetz


2 Answers

We can resolve it with the below. Hope it's helpful.

public class TestPaperResultId: ValueObject
{
    public TestPaperResultId(string testPaperId, string userId)
    {
        TestPaperId = testPaperId;
        UserId = userId;
    }

    protected TestPaperResultId() { }

    public string TestPaperId { get; protected set; }
    public string UserId { get; protected set; }

    public override string ToString()
    {
        return $"{TestPaperId}_{UserId}";
    }
}

public class TestPaperResult : AggregateRoot
{
    private TestPaperResultId _id;

    public TestPaperResultId Id
    {
        get => _id ?? (_id = new TestPaperResultId(TestPaperId, UserId));
        protected set
        {
            TestPaperId = value.TestPaperId;
            UserId = value.UserId;
            _id = value;
        }
    }

    public string TestPaperId { get; protected set; }

    public string UserId { get; protected set; }

    protected TestPaperResult() { }

    public TestPaperResult(TestPaperResultId id,
                           decimal fullmarks)
    {
        Id = id;
        Fullmarks = fullmarks;
    }
}

in dbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<TestPaperResult>()
                .Ignore(t => t.Id)
                .HasKey(t => new {t.TestPaperId, t.UserId});
 }

in Repository:

 public Task<TestPaperResult> FindTestPaperResultAsync(TestPaperResultId id)
 {
     return GetByKeyAsync<TestPaperResult>(id.TestPaperId, id.UserId);
 }
like image 20
Ivan Zheng Avatar answered Sep 28 '22 03:09

Ivan Zheng


This is the limitation. Key members can be only scalar properties directly in the entity. Complex type is represented as complex property which is not supported.

like image 185
Ladislav Mrnka Avatar answered Sep 28 '22 04:09

Ladislav Mrnka