3

J'utilise des codes POCO d'abord avec EF4, CTP5. J'ai une table avec beaucoup de colonnes (plus de 100). Je veux diviser la table en plusieurs types (aka "Table Splitting") de sorte que je n'ai pas à aller chercher toutes les données chaque fois que je veux des informations de base.Comment diviser un tableau en plusieurs types dans le code EF4 en premier?

Je n'arrive pas à trouver de documentation à ce sujet en utilisant Google. J'ai trouvé des références au concept, "Table Splitting", et j'ai aussi vu comment le faire en utilisant un fichier EDMX, mais pas d'échantillons pour le code d'abord.

J'espérais que ce serait aussi simple que la définition d'un autre type d'entité et les concernant comme tout autre propriété de navigation comme si ...

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 
} 

Et je l'appelle comme ça ...

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

Malheureusement, cela ne semble pas fonctionner. Je reçois l'erreur suivante quand je fais cela ...

[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 

Retrait de la propriété User.Details fait l'erreur aller, mais je ne peux pas utiliser les fonctions de navigation astucieuses de EF4.

Répondre

4

En utilisant Types complexes est la seule façon que vous pouvez mapper une table à plusieurs types. Cependant, Code First (et EF en général) ne prend pas en charge le chargement paresseux/différé pour les types complexes. En d'autres termes, EF toujours remplir le type complexe à chaque fois que vous avez lu l'entité de la base de données:

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

La seule façon que vous pouvez réaliser le chargement paresseux pour votre grande table est par elle diviser vraiment en plusieurs tables, puis vous pouvez utiliser des associations un-à-un pour le mapper à plusieurs entités.

Pour plus d'information concernant les types complexes dans EF premier code CTP, jetez un oeil à cet article:
Associations in EF Code First CTP5: Part 1 – Complex Types

+0

Merci. J'espérais une meilleure solution. Je commence à me demander si je dois passer à NHibernate pour prendre en charge notre base de données existante – Brian

+0

Désolé, je voudrais avoir une meilleure réponse pour vous, je pense que NHibernate supporte cette fonctionnalité sur les types complexes (ils l'appellent * Components * c'est le même concept.) Malheureusement, il s'agit d'un élément de faible priorité pour l'équipe EF, il est donc très peu probable que nous recevions cette fonctionnalité dans le RTM plus tard cette année –

+0

@Brian: Utilisez simplement la projection dans vos requêtes et vous serez OK. Ou abandonner avec Code First et utiliser la fonctionnalité QueryView. –

0

Je sais que cette question est plus d'un an, mais le code EF premier prend en charge le fractionnement de la table et le chargement paresseux en même temps.

Votre modèle doit ressembler à ceci:

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

chargement Lazy (et le chargement désireux) devrait fonctionner comme prévu.

Il est important de noter que le fractionnement du tableau fonctionne si

  • entités ont 1 à 1 relation et
  • entités partagent la même clé
0

Je suppose que la réponse proposée par Rino est un meilleur. Bien qu'à la fin vous réalisiez la même chose. Mais dans le cas de la seconde, il est fait exactement la même chose. Le premier peut poser problème lorsque vous ne pouvez pas appliquer [ComplexType] en raison d'un code tiers ou si vous avez une liste de ce type.

Utilisez le deuxième ou dans les API Fluent comme du livre de Julia Lerman (division tableau « People » dans « Personne » et les entités « PersonPhoto ».

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