如何首先将表拆分为EF4代码中的多种类型?

时间:2011-01-19 19:29:33

标签: entity-framework-4 code-first ef-code-first ef4-code-only

我正在使用带有EF4,CTP5的代码优先POCO。我有一张桌子上有很多列(超过100个)。我想将表拆分为多种类型(也称为“表拆分”),这样我每次想要一些基本信息时都不必获取所有数据。

我似乎无法使用Google找到任何相关文档。我发现了对“Table Splitting”这个概念的引用,我也看到了如何使用EDMX文件,但没有代码优先的样本。

我希望它可以像定义另一个实体类型一样简单并将它们与任何其他导航属性相关联,就像这样......

public class User
{
    public int UserID { get; set; }
    public string UserName { get; set; }
    [ForeignKey("UserID")]
    public virtual UserDetails Details { get; set; }
}

public class UserDetails
{
    public int UserID { get; set; }
    public string MoreData { get; set; }
    [ForeignKey("UserID")]
    public virtual User User { get; set; } // nice to have, but not required
}

我称之为......

return (from u in Context.Users  // <-- error occurs here
        where u.UserID == userID
        select u).FirstOrDefault();

不幸的是,这似乎不起作用。当我这样做时,我收到以下错误...

[IndexOutOfRangeException: Index was outside the bounds of the array.]
   System.Data.Entity.ModelConfiguration.Conventions.Edm.PropertyMaxLengthConvention.System.Data.Entity.ModelConfiguration.Conventions.Edm.IEdmConvention<System.Data.Edm.EdmAssociationType>.Apply(EdmAssociationType associationType, EdmModel model) +598
   System.Data.Entity.ModelConfiguration.Configuration.EdmConventionDispatcher.Dispatch(TEdmDataModelItem item) +100
   System.Data.Entity.ModelConfiguration.Configuration.EdmConventionDispatcher.VisitEdmAssociationType(EdmAssociationType item) +22
   System.Data.Entity.ModelConfiguration.Edm.Services.DataModelItemVisitor.VisitCollection(IEnumerable`1 collection, Action`1 visitMethod) +267
   System.Data.Entity.ModelConfiguration.Edm.Services.EdmModelVisitor.VisitAssociationTypes(EdmNamespace edmNamespace, IEnumerable`1 associationTypes) +75
   System.Data.Entity.ModelConfiguration.Edm.Services.EdmModelVisitor.VisitEdmNamespace(EdmNamespace item) +91
   System.Data.Entity.ModelConfiguration.Configuration.EdmConventionDispatcher.VisitEdmNamespace(EdmNamespace item) +32
   System.Data.Entity.ModelConfiguration.Edm.Services.DataModelItemVisitor.VisitCollection(IEnumerable`1 collection, Action`1 visitMethod) +267
   System.Data.Entity.ModelConfiguration.Edm.Services.EdmModelVisitor.VisitNamespaces(EdmModel model, IEnumerable`1 namespaces) +75
   System.Data.Entity.ModelConfiguration.Edm.Services.EdmModelVisitor.VisitEdmModel(EdmModel item) +47
   System.Data.Entity.ModelConfiguration.Configuration.EdmConventionDispatcher.VisitEdmModel(EdmModel item) +45
   System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModel(EdmModel model) +254
   System.Data.Entity.ModelConfiguration.ModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo, Boolean validateModel) +257
   System.Data.Entity.ModelConfiguration.ModelBuilder.Build(DbConnection providerConnection) +172
   System.Data.Entity.Internal.LazyInternalContext.CreateModel() +62
   System.Lazy`1.CreateValue() +361
   System.Lazy`1.LazyInitValue() +104
   System.Lazy`1.get_Value() +89
   System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +358
   System.Data.Entity.Internal.InternalContext.Initialize() +16
   System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +16
   System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +61
   System.Data.Entity.Internal.Linq.InternalSet`1.get_Provider() +15
   System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +13
   System.Linq.Queryable.Where(IQueryable`1 source, Expression`1 predicate) +63
   TourFactory.Web.AgentWebsite.Models.Websites.WebsiteRepository.GetUser(Int32 userID) in C:\Code\hdtf\TF4\Web\AgentWebsite\Models\Websites\WebsiteRepository.cs:28
   TourFactory.Web.AgentWebsite.Controllers.WebsiteController.get_Agent() in C:\Code\hdtf\TF4\Web\AgentWebsite\Controllers\WebsiteController.cs:42
   TourFactory.Web.AgentWebsite.Controllers.WebsiteController.OnActionExecuting(ActionExecutingContext filterContext) in C:\Code\hdtf\TF4\Web\AgentWebsite\Controllers\WebsiteController.cs:55
   System.Web.Mvc.Controller.System.Web.Mvc.IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) +39
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +81
   System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +61
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +305
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830
   System.Web.Mvc.Controller.ExecuteCore() +136
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +232
   System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +68
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44
   System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +42
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +141
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +54
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +61
   System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +31
   System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +56
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +110
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

删除User.Details属性会使错误消失,但我无法使用EF4的漂亮导航功能。

3 个答案:

答案 0 :(得分:4)

使用 复杂类型 是将表格映射到多种类型的唯一方法。但是,Code First(和一般的EF)不支持复杂类型的延迟/延迟加载。换句话说,每次从数据库中读取实体时,EF都会始终填充复杂类型:

public class User
{
    public int UserID { get; set; }
    public string UserName { get; set; }
    public UserDetails Details { get; set; }
}

[ComplexType]
public class UserDetails
{
    public string MoreData { get; set; }
}

实现大表延迟加载的唯一方法是将其拆分为多个表,然后使用一对一关联将其映射回多个实体。

有关EF Code First CTP中复杂类型的更多信息,请查看以下文章:
Associations in EF Code First CTP5: Part 1 – Complex Types

答案 1 :(得分:0)

我知道这个问题超过一年,但EF Code First同时支持表拆分和延迟加载。

你的模型应该是这样的:

[Table("UserTable")]
public class User
{
    [Key, ForeignKey("Details")]
    public int UserID { get; set; }
    public string UserName { get; set; }
    public virtual  UserDetails Details { get; set; }
}

[Table("UserTable")]
public class UserDetails
{

    [Key, ForeignKey("User")]
    public int UserID { get; set; }
    public string MoreData { get; set; }
    public virtual User User { get; set; }
}

延迟加载(和急切加载)应该按预期工作。

重要的是要注意表分割是否有效

  • 实体具有一对一关系,
  • 实体共享相同的密钥

答案 2 :(得分:0)

我猜Rino建议的答案更好。虽然最终你实现了同样的目标。但是在第二个的情况下,它意味着做同样的事情。如果由于第三方代码而无法应用[ComplexType]或者您有该类型的列表,则第一个可能会出现问题。

使用第二个或在Fluent API中使用Julia Lerman的书(将“People”表分为“Person”和“PersonPhoto”实体。

   modelBuilder.Entity<Person>().ToTable("People");
   modelBuilder.Entity<PersonPhoto>().ToTable("People");