问题
根据我之前的问题,我正在尝试使用表拆分来共享大约 7 个实体的大表(200 多个字段)。
EF6 不仅需要从主模型到子模型的导航属性,还需要所有子模型之间的导航属性(这很糟糕)。
手动解决方案
这可以手动完成:
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...
}
使用流畅的映射:
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);
}
}
这行得通。但这不会不适用于 7+ 模型。
尝试改进#1
我想通过继承+ DRY原则改进:
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...
但是在第一次请求时失败,“序列包含多个匹配元素”:
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
尝试改进#2
我以为我可以将它们声明为抽象的,因此至少程序员被迫实现正确的成员(仍然很糟糕在每个派生类上重新声明):
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
但这失败时同样的错误。啊??类定义与工作副本相同,只是它们被声明为“覆盖”而不是“虚拟”。就好像 E/F 正在索引 PropertyInfos 或不考虑 PropertyInfo.ReflectedType 的东西
尝试改进#3
我可以使用接口强制执行该模式,但这不太可取,因为必须在每个类上声明接口,这开始看起来很奇怪:
public class Franchise : SharedFranchiseIdBase, ISharedFranchiseId { ... }
public class FranchiseEntity : SharedFranchiseIdBase, ISharedFranchiseId { ... }
public class FranchiseMiscellaneous : SharedFranchiseIdBase, ISharedFranchiseId { ... }
嗯?
这是 E/F 中的一个错误,它很难将基类上的属性与派生类上的属性相同吗?
抱歉冗长的解释,这是今天上午整个调查的总结。