2012-08-14 20 views
8

que tienen la siguiente estructura de datos:Marco de la entidad multiusuario arquitectura de datos compartida: una sola columna, varias claves externas

//property Notification 
abstract class BindableBase { } 
//base class for all tenant-scoped objects 
abstract class TenantModelBase : BindableBase 
{ 
    int TenantId; 
} 

abstract class Order : TenantModelBase 
{ 
    Customer Customer; //works: mapped using TenantId and CustomerId 
    Product Product; //again, works with TenantId and ProductId 
    string ProductId; 
    string CustomerId; 
} 
class Customer: TenantModelBase 
{ 
    string CustomerId; 
} 

class Product : TenantModelBase 
{ 
    string ProductId; 
} 

class SpecialOrder : Order 
{ 
    OtherClass OtherClass; //this fails!, see below 
    string OtherClassId; 
} 
class SuperSpecialOrder : SpecialOrder { } 

class OtherClass : TenantModelBase 
{ 
    string OtherClassId; 
} 

me sale el siguiente error:

The foreign key component 'TenantId' is not a declared property on type 'SpecialOrder'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property.

error se produce utilizando la configuración de la API Fluido :

 config.HasRequired(p => p.OtherClass) 
      .WithMany(oc => oc.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId}); 

Sin la referencia en OtherClassSpecialOrder Puedo crear objetos libremente sin problemas (incluidos SpecialOrder, SuperSpecialOrder, etc.).

¿Alguien tiene una idea de lo que está pasando? Estoy perdido aquí :(

Editar que he visto en otras preguntas que la gente saque el mecanismo TenantId de las tablas, esto no es una opción ya que las claves primarias no son únicos a través de los inquilinos y queremos mantener el compartida arquitectura de datos.

sé que la solución es tener una segunda TenantId en la clase SpecialOrder, pero esto no parece lógico.

+0

Creo que es el mismo tipo de problema como este: http: // stackoverflow.com/questions/10961690/inheritance-and-composite-foreign-keys-one-part-of-the-key-in-base-class-the ¿Podría mostrar su asignación de forma más precisa? ¿Qué es 'config'? Supongo que una 'EntityTypeConfiguration 'con' T' = 'SpecialOrder', ¿verdad? ¿Cómo se ve el mapeo de 'Order.Customer'? ¿Creas este mapeo con 'T' =' SpecialOrder' o 'T' =' Order'? – Slauma

+0

El problema surge cuando especifico una asignación para Order y SpecialOrder. Luego pierde de vista cualquier propiedad declarada en la clase base en SpecialOrder. Parece ser la misma pregunta de hecho. – Bas

Respuesta

7

¿Estás tratando de hacer un TPT, donde hay una tabla independiente para el pedido/¿Inquilino? Si es así, creo que el otro póster es correcto, y hay un error en EF.

Si los clientes/productos son sus clases mapeadas, esto podría funcionar para usted.

Lo que me sucedió cuando creé su base de datos es que intentó mapear la clase de orden abstracta.

Añadiendo:

modelBuilder.Ignore<Order>(); 

El constructor mantienen las propiedades asignadas debido a los MapInheritedProperties, pero no crearon la mesa para que todo el FK fueron creados correctamente.

Supongo que quería tablas separadas para cada una de sus clases, como la publicación relacionada anterior, y para no asignar su tabla de resumen.

modelo completo:

public abstract class BindableBase { } 
    //base class for all tenant-scoped objects 
    public abstract class TenantModelBase : BindableBase 
    { 
     [Key] 
     public virtual int TenantId { get; set; } 
    } 

    public abstract class Order : TenantModelBase 
    { 
     public Customer Customer { get; set; } //works: mapped using TenantId and CustomerId 
     public Product Product { get; set; } //again, works with TenantId and ProductId 
     public string ProductId { get; set; } 
     public string CustomerId { get; set; } 
    } 
    public class Customer : TenantModelBase 
    { 
     [Key] 
     public string CustomerId { get; set; } 
    } 

    public class Product : TenantModelBase 
    { 
     [Key] 
     public string ProductId { get; set; } 
    } 

    public class SpecialOrder : Order 
    { 
     [Key] 
     public int SpecialOrderId { get; set; } 
     public OtherClass OtherClass { get; set; } //this fails!, see below 
     public string OtherClassId { get; set; } 
    } 
    public class SuperSpecialOrder : SpecialOrder { } 

    public class OtherClass : TenantModelBase 
    { 
     public string OtherClassId { get; set; } 
     public ICollection<SpecialOrder> SpecialOrders { get; set; } 
    } 



    public class Model : DbContext 
    { 
     public DbSet<Customer> Customers { get; set; } 
     public DbSet<Product> Products { get; set; } 
     public DbSet<SpecialOrder> SpecialOrders { get; set; } 
     public DbSet<SuperSpecialOrder> SuperSpecialOrders { get; set; } 

     public DbSet<OtherClass> OtherClasses { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
     modelBuilder.Entity<OtherClass>() 
      .HasKey(k => new { k.TenantId, k.OtherClassId }); 

     modelBuilder.Entity<Customer>() 
      .HasKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Product>() 
      .HasKey(k => new { k.TenantId, k.ProductId }); 


     modelBuilder.Entity<SpecialOrder>() 
      .Map(m => 
        { 
         m.MapInheritedProperties(); 
         m.ToTable("SpecialOrders"); 
        }); 

     modelBuilder.Entity<SpecialOrder>().HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SuperSpecialOrder>() 
      .Map(m => 
      { 
      m.MapInheritedProperties(); 
      m.ToTable("SuperSpecialOrders"); 
      }) 
      .HasKey(k => new { k.TenantId, k.SpecialOrderId }); 

     modelBuilder.Entity<SpecialOrder>() 
      .HasRequired(p => p.OtherClass) 
      .WithMany(o => o.SpecialOrders) 
      .HasForeignKey(p => new { p.TenantId, p.OtherClassId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Customer) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.CustomerId }); 

     modelBuilder.Entity<Order>() 
      .HasRequired(o => o.Product) 
      .WithMany() 
      .HasForeignKey(k => new { k.TenantId, k.ProductId }); 

     modelBuilder.Ignore<Order>(); 


     } 
    } 

Creado Base de datos: enter image description here

Espero que esto ayude.

+0

+1: ¡Análisis interesante! Veo que no mapear la clase 'Order' resuelve el problema particular en la pregunta, pero me pregunto si el problema no solo se mueve un nivel hacia arriba en la jerarquía de herencia. Imagine, 'SuperSpecialOrder' tenía ahora una referencia a' OtherClass'. Debido a que la clase base 'SpecialOrder' está mapeada ahora, supongo que el mapeo FK compuesto en' SuperSpecialOrder' arrojaría la misma excepción ahora. Además, ¿se requiere la asignación de TPC en lugar de TPT para que funcione? – Slauma

+0

Esta parece ser la única solución, debemos abandonar el mapeo TPH. ¡Gracias por la gran respuesta! – Bas

0

Voy a adivinar aquí ya que vi un error inusual en un blog que Julie Lermann hizo con ef4.1 El espacio de nombres en la consulta causó un problema.

Solo para probar rápidamente si este problema es su problema, cambie el espacio de nombres de todos los objetos para que sean iguales. Espacio de nombres xyz // igual que dbcontext yy entidades clase pública OtherClass {}

Prueba rápida. Si no es así, perdón por perder tu tiempo.

+0

Hola soadyp, gracias por tu aporte, ¡pero todas las clases ya están en el mismo espacio de nombres! – Bas

Cuestiones relacionadas