11

Actualmente estoy tratando de implementar los repositorios para mis objetos de dominio con el RC de Entity Framework 4.1 y su primera aproximación de código. ahora tengo una entidad del dominio "Viaje", que tiene un identificador único encapsulado en el tipo "VoyageNumber"Primer código EF4.1 Primer tipo como clave principal

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; } 
    } 

ahora consigo una excepción cuando hago esto en la configuración de mi DbContext:

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

la propiedad 'VoyageNumber' no puede ser utilizado como una propiedad clave de la entidad 'Domain.Model.Voyages.Voyage' porque el tipo de propiedad no es una clave válida tipo. Solo los tipos escalares, cadena y byte [] son ​​tipos de clave admitidos.

y también cuando intento esto:

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

La expresión propiedades 'k => k.VoyageNumber.Id' no es válido. La expresión debe representar un propiedad: C#: 't => t.MyProperty'

¿Realmente tengo a la basura mi VoyageNumber y reemplazarlo con un tipo primitivo?

+0

¿Cuál es el mensaje de excepción cuando se utiliza este: modelBuilder.Entity () .HasKey (k = > k.VoyageNumber); – tpeczek

+0

Actualizó la pregunta con los mensajes de excepción. – hoetz

+0

sigue siendo el caso en EF 6.1.3 –

Respuesta

14

Esta es la limitación. Los miembros clave pueden ser solo propiedades escalares directamente en la entidad. El tipo complejo se representa como propiedad compleja que no es compatible.

+0

Qué lástima, entonces supongo que me rendiré en el código primero, ya que no estoy dispuesto a renunciar a la encapsulación de la clave principal. – hoetz

+0

No estaba claro. Es la limitación del marco de la Entidad. No solo la limitación del código primero. –

+5

¿Sigue siendo cierto en EF6? Obtengo el mismo error documentado en las preguntas originales, así que supongo que nada ha cambiado, pero espero que se haya agregado alguna opción de configuración que me falta. – sellmeadog

0

Para una clase aislada, puede hacer una solución de solo lectura agregando un método "get" a su DbContext que hace un SqlQuery<> y asigna la tabla a la clase internamente (a la manera antigua).

he trabajado un caso de prueba mínima aquí: https://github.com/timabell/ef-complex-pk

por ejemplo,

public class TestDbContext : DbContext 
{ 

    public IEnumerable<UberWidget> GetUberWidgets() 
    { 
     return Database.SqlQuery<WidgetSqlDto>("select WidgetId, Name from Widgets") 
      .Select(dto => new UberWidget 
      { 
       UberWidgetId = new IdWrap { IdWrapId = dto.WidgetId }, 
       Name = dto.Name 
      }); 
    } 
} 
0

Podemos resolverlo con lo siguiente. Espero que sea útil.

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; 
    } 
} 

en dbContext:

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

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

en el repositorio:

public Task<TestPaperResult> FindTestPaperResultAsync(TestPaperResultId id) 
{ 
    return GetByKeyAsync<TestPaperResult>(id.TestPaperId, id.UserId); 
}