I am using code-first POCOs with EF4, CTP5. I've got a table with a lot of columns in it (over 100). I want to split the table into multiple types (aka "Table Splitting") so that I don't have to fetch all the data every time I want some basic information.
I can't seem to find any documentation on this using Google. I've found references to the concept, "Table Splitting", and I've also seen how to do it using an EDMX file, but no samples for code-first.
I was hoping it would be as simple as defining another entity type and relating them as you would any other navigation property like so...
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
}
And I call it like this...
return (from u in Context.Users // <-- error occurs here
where u.UserID == userID
select u).FirstOrDefault();
Unfortunately this does not seem to be working. I am getting the following error when I do this...
[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
Removing the User.Details property makes the error go away, but then I can't use the nifty navigation features of EF4.
Using Complex Types is the only way you can map a table to multiple types. However, Code First (and EF in general) does NOT support lazy/Deferred loading for complex types. In other words, EF will always populate the complex type each time you read the entity from the database:
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; }
}
The only way you can achieve lazy loading for your big table is by really splitting it into multiple tables and then you can use one-to-one associations to map it back to multiple entities.
For more info regarding Complex Types in EF Code First CTP, take a look at this article:
Associations in EF Code First CTP5: Part 1 – Complex Types