3

Я использую кодовые POCOs с EF4, CTP5. У меня есть таблица с большим количеством столбцов (более 100). Я хочу разбить таблицу на несколько типов (ака «Разделение таблицы»), так что мне не нужно извлекать все данные каждый раз, когда мне нужна какая-то основная информация.Как мне сначала разбивать таблицу на несколько типов в коде EF4?

Возможно, я не могу найти документацию по этому вопросу с помощью Google. Я нашел ссылки на концепцию «Разделение таблиц», и я также видел, как это сделать, используя 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 Code First CTP, посмотрите на эту статью:
Associations in EF Code First CTP5: Part 1 – Complex Types

+0

Спасибо. Я надеялся на лучшее решение. Я начинаю задаваться вопросом, нужно ли мне переключиться на NHibernate для поддержки нашей старой базы данных. – Brian

+0

Извините, чувак, мне жаль, что у меня не было лучшего ответа. Я думаю, что NHibernate поддерживает эту функцию в сложных типах (они называют это * Компоненты *, но это одна и та же концепция.) К сожалению, это низкоприоритетный элемент для команды EF, поэтому очень маловероятно, что мы получим эту функцию в RTM в конце этого года. –

+0

@Brian: Просто используйте прогноз в своих запросах, и все будет в порядке. Или отказаться от кода сначала и использовать функцию QueryView. –

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

Ленивая загрузка (и жадная загрузка) должна работать, как ожидалось.

важно отметить, что таблица расщепление работает, если

  • Сущность имеет 1-к-1 отношение, и
  • Сущности один и тот же ключ
0

Я думаю, ответ предложенного Рино является лучшим. Хотя, в конце концов, вы достигаете того же. Но в случае второго это означает сделать то же самое. Во-первых, может возникнуть проблема, если вы не можете применить [ComplexType] из-за стороннего кода или у вас есть список этого типа.

Используйте вторую один или в Fluent API, а из книги Джулии Лермана (расщепление «Люди» стол в «Человек» и «PersonPhoto» сущности.

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