3

我正在使用代碼優先的POCO與EF4,CTP5。我有一張桌子上有很多列(超過100)。我想將表格拆分成多種類型(又稱「表格拆分」),這樣我就不必每次都需要獲取一些基本信息時獲取所有數據。如何首先在EF4代碼中將表分成多個類型?

我似乎無法找到任何有關此使用谷歌的文檔。我發現了「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的漂亮的導航功能。

回答

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代碼第一次CTP複雜類型更多的信息,看看這篇文章:
Associations in EF Code First CTP5: Part 1 – Complex Types

+0

感謝。我希望的是更好的解決方案。我開始懷疑我是否需要切換到NHibernate的支持我們的傳統數據庫。 – Brian 2011-01-19 21:19:30

0

我知道這個問題是不是一年,但EF代碼優先支持表分割和延遲加載更多與此同時。

你的模型應該是這樣的:

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

延遲加載(和熱切加載)應該按預期工作。

其需要注意的是表拆分工作,如果

  • 實體有1對1的關係,並
  • 實體共享由綠諾國際建議的相同的密鑰
0

我想答案是一個更好的。儘管最終你達到了同樣的目的。但在第二種情況下,它意味着要做同樣的事情。如果由於第三方代碼而無法應用[ComplexType],或者您有該類型的列表,則首先可能會出現問題。

使用第二個或作爲流利的API從朱莉婭·勒曼的著作(分裂「人物」表分爲「人」和「PersonPhoto」的實體。

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