Question

le problème

J'essaie de partager une grande table (200 + champs) environ environ 7 entités à l'aide de la division de table selon ma question précédente .

EF6 nécessite des propriétés de navigation non seulement du modèle principal aux modèles enfants, mais entre tous les modèles enfants (qui craint).

solution manuelle

Ceci peut être fait manuellement:

public class Franchise
{
    [Key]
    public int Id { get; set; }
    public virtual FranchiseEntity Entity { get; set; }
    public virtual FranchiseMiscellaneous Miscellaneous { get; set; }
}

[Table("Franchise")]
public class FranchiseEntity
{
    [Key]
    public int Id { get; set; }
    public virtual FranchiseEntity Entity { get; set; } // Ignored, but relevant when inheritance involved, below...
    public virtual FranchiseMiscellaneous Miscellaneous { get; set; }
}

[Table("Franchise")]
public class FranchiseMiscellaneous
{
    [Key]
    public int Id { get; set; }
    public virtual FranchiseEntity Entity { get; set;
    public virtual FranchiseMiscellaneous Miscellaneous { get; set; }  // Ignored, but relevant when inheritance involved, below...
}

avec des mappages fluides:

public class FranchiseMapping : EntityTypeConfiguration<Franchise>
{
    public FranchiseMapping()
    {
        HasRequired(x => x.Entity).WithRequiredPrincipal();
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal();
    }
}

public class FranchiseEntityMapping : EntityTypeConfiguration<FranchiseEntity>
{
    public FranchiseEntityMapping()
    {
        Ignore(x => x.Entity);
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal(x => x.Entity);
    }
}

public class FranchiseMiscellaneousMapping : EntityTypeConfiguration<FranchiseMiscellaneous>
{
    public FranchiseMiscellaneousMapping()
    {
        Ignore(x => x.Miscellaneous);
    }
}

cela fonctionne. Mais cela ne va pas bien augmenter avec 7 modèles et plus de 7 modèles.

tentative d'améliorer # 1

J'aimerais m'améliorer à travers héritage + principe sec:

public abstract class SharedFranchiseIdBase
{
    [Key]
    public int Id { get; set; }
    public virtual FranchiseEntity Entity { get; set; }
    public virtual FranchiseMiscellaneous Miscellaneous { get; set; }
}

public class Franchise : SharedFranchiseIdBase { ... }

public class FranchiseEntity : SharedFranchiseIdBase { ... }

public class FranchiseMiscellaneous : SharedFranchiseIdBase { ... }

// Maybe generalize the mapping code too...

Mais cela échoue sur la première demande avec "séquence contient plus d'un élément de correspondance":

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Sequence contains more than one matching element
Result StackTrace:  
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
   at System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.NavigationPropertyConfiguration.ConfigureDependentBehavior(AssociationType associationType, EdmModel model, EntityTypeConfiguration entityTypeConfiguration)
   at System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation.NavigationPropertyConfiguration.Configure(NavigationProperty navigationProperty, EdmModel model, EntityTypeConfiguration entityTypeConfiguration)
   at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureAssociations(EntityType entityType, EdmModel model)
   at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EntityType entityType, EdmModel model)
   at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel model)
   at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
   at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   ... // my test query function

tentative d'améliorer # 2

Je pensais que je pourrais les déclarer abstrait, donc au moins les programmeurs sont obligés de mettre en œuvre les bons membres (craint toujours de refluer de nouveau sur chaque classe dérivée):

public abstract class SharedFranchiseIdBase
{
    [Key]
    public int Id { get; set; }
    public abstract FranchiseEntity Entity { get; set; }
    public abstract FranchiseMiscellaneous Miscellaneous { get; set; }
}

public class Franchise : SharedFranchiseIdBase
{
    [Key]
    public int Id { get; set; }
    public override FranchiseEntity Entity { get; set; }
    public override FranchiseMiscellaneous Miscellaneous { get; set; }
}
//etc for other classes

Mais cela échoue lorsque la même erreur. Hein?? Les définitions de la classe sont identiques comme la copie de travail, sauf qu'ils sont déclarés "remplacent" au lieu de "virtuels". C'est comme si E / F soit indexé sur des biensInfos ou quelque chose sans égard pour la propriétéInfo.reflefledType

tentative d'améliorer # 3

Je pourrais appliquer le modèle à l'aide d'une interface, mais cela est moins préférable car l'interface doit être déclarée sur chaque classe qui commence à regarder assez bizarre:

public class Franchise : SharedFranchiseIdBase, ISharedFranchiseId { ... }

public class FranchiseEntity : SharedFranchiseIdBase, ISharedFranchiseId { ... }

public class FranchiseMiscellaneous : SharedFranchiseIdBase, ISharedFranchiseId { ... }

hein?

Est-ce un bogue dans E / F, qu'il lutte pour traiter les propriétés de la classe de base identiques à celles des classes dérivées?

excuses pour l'explication à long terme, c'est le résumé de l'ensemble de l'enquête de ce matin.

Était-ce utile?

La solution

En fin de compte, j'ai décidé d'adopter la solution manuelle car je ne pouvais obtenir aucune des tentatives d'amélioration de travailler.

Le code et les modèles ne sont pas élégants, mais à la fin de la journée, il fonctionne bien.J'ai mis en place le motif dans 3 zones et effectuer la mesure requise dans le domaine et sur la couche SQL.

Pour soulager la douleur et fournir aux développeurs de manière cohérente de travailler avec ce modèle, j'ai créé cette interface pour appliquer toutes les relations:

public interface ISharedFranchiseId
{
    FranchiseBilling Billing { get; set; }
    FranchiseCompliance Compliance { get; set; }
    FranchiseLeadAllocation LeadAllocation { get; set; }
    FranchiseMessaging Messaging { get; set; }
    FranchiseMiscellaneous Miscellaneous { get; set; }
    FranchiseSignup Signup { get; set; }
}

Donc, chacun des modèles partageant la clé principale a ces propriétés (le bit gênant):

public class FranchiseBilling/Compliance/etc : ISharedFranchiseId
{
    // Properties implemented on this model
    #region Navigations to other entities sharing primary key
    public virtual FranchiseBilling Billing { get; set; }
    public virtual FranchiseCompliance Compliance { get; set; }
    public virtual FranchiseLeadAllocation LeadAllocation { get; set; }
    public virtual FranchiseMessaging Messaging { get; set; }
    public virtual FranchiseMiscellaneous Miscellaneous { get; set; }
    public virtual FranchiseSignup Signup { get; set; }
    #endregion
}

et configurer via API fluide comme suit (le bit douloureux):

// Franchise = the "primary/parent" model
public class FranchiseMapping : EntityTypeConfiguration<Franchise>
{
    public FranchiseMapping()
    {
        HasRequired(x => x.Billing).WithRequiredPrincipal();
        HasRequired(x => x.Compliance).WithRequiredPrincipal();
        HasRequired(x => x.LeadAllocation).WithRequiredPrincipal();
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal();
        HasRequired(x => x.Messaging).WithRequiredPrincipal();
        HasRequired(x => x.Signup).WithRequiredPrincipal();
    }
}

// Now each "child" model gets link to all the others. We only need links going one way,
// So each model links to the ones listed below.
// This makes it easy to implement an extra child model down the track as we just
// insert the configuration it here and copy from the next one.
public class FranchiseBillingMapping : EntityTypeConfiguration<FranchiseBilling>
{
    public FranchiseBillingMapping()
    {
        Ignore(x => x.Billing);
        HasRequired(x => x.Compliance).WithRequiredDependent(x => x.Billing);
        HasRequired(x => x.LeadAllocation).WithRequiredPrincipal(x => x.Billing);
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal(x => x.Billing);
        HasRequired(x => x.Messaging).WithRequiredPrincipal(x => x.Billing);
        HasRequired(x => x.Signup).WithRequiredPrincipal(x => x.Billing);
    }
}

public class FranchiseComplianceMapping : EntityTypeConfiguration<FranchiseCompliance>
{
    public FranchiseComplianceMapping()
    {
        Ignore(x => x.Compliance);
        HasRequired(x => x.LeadAllocation).WithRequiredPrincipal(x => x.Compliance);
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal(x => x.Compliance);
        HasRequired(x => x.Messaging).WithRequiredPrincipal(x => x.Compliance);
        HasRequired(x => x.Signup).WithRequiredPrincipal(x => x.Compliance);
    }
}

public class FranchiseLeadAllocationMapping : EntityTypeConfiguration<FranchiseLeadAllocation>
{
    public FranchiseLeadAllocationMapping()
    {
        Ignore(x => x.LeadAllocation);
        HasRequired(x => x.Miscellaneous).WithRequiredPrincipal(x => x.LeadAllocation);
        HasRequired(x => x.Messaging).WithRequiredPrincipal(x => x.LeadAllocation);
        HasRequired(x => x.Signup).WithRequiredPrincipal(x => x.LeadAllocation);
    }
}

public class FranchiseeMiscellaneousMapping : EntityTypeConfiguration<FranchiseeMiscellaneous>
{
    public FranchiseeMiscellaneousMapping()
    {
        Ignore(x => x.Miscellaneous);
        HasRequired(x => x.Messaging).WithRequiredPrincipal(x => x.Miscellaneous);
        HasRequired(x => x.Signup).WithRequiredPrincipal(x => x.Miscellaneous);
    }
}

public class FranchiseMessagingMapping : EntityTypeConfiguration<FranchiseMessaging>
{
    public FranchiseMessagingMapping()
    {
        Ignore(x => x.Messaging);
        HasRequired(x => x.Signup).WithRequiredPrincipal(x => x.Messaging);
    }
}

public class FranchiseSignupMapping : EntityTypeConfiguration<FranchiseSignup>
{
    public FranchiseSignupMapping()
    {
        Ignore(x => x.Signup);
    }
}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top