Impossible de sauvegarder les types Entity Framework Inherited

.net entity-framework inheritance savechanges table-per-type

Question

J'ai implémenté un héritage table par type dans mon modèle de données (essentiellement un type BaseEntity avec toutes les informations de base de mes éléments et un type Employer héritant de l'élément BaseEntity ). Tout semble être configuré correctement et lors de l'utilisation d'entités (via ADO.net Data Services ou via Linq to Entities), je peux voir le type d' Employer et tout semble aller pour le mieux. Le problème commence lorsque je crée une nouvelle entité Employer et tente de la sauvegarder.

Sur le contexte qui ne semble pas être un élément .AddToEmployer (uniquement et AddObject ou AddToBaseEntity ).

Si j'utilise AddObject("Employer", NewEmployer) , le message d'erreur suivant s'affiche:

Le nom EntitySet 'DataEntities.Employer' est introuvable.

Si j'utilise AddToBaseEntity(NewEmployer) je reçois un message d'erreur de:

Impossible de déterminer un ordre valide pour les opérations dépendantes. Des dépendances peuvent exister en raison de contraintes de clé étrangère, d'exigences de modèle ou de valeurs générées par le magasin.

Ai-je manqué une étape dans la mise en place de l'héritage? Existe-t-il un moyen spécifique de sauvegarder les objets hérités? Qu'est-ce que je fais mal? Je suppose que le problème fondamental est que je devrais avoir un AddToEmployer , que dois-je faire pour que cela soit exposé? Il semble étrange que ce ne soit pas une option puisque je peux voir le type d’employeur du côté client et pouvoir faire des choses telles que:

var NewEmployer = new Employer() - ce qui semble suggérer que je peux voir le type d’employeur très bien.

Réponse acceptée

J'ai changé plusieurs choses et j'ai réussi à faire en sorte que cela fonctionne. Je ne suis pas particulièrement sûr de savoir quel était le problème de base, mais je voulais publier ce que j'ai fait à titre de référence.

Tables reconstruites: j'ai reconstruit les tables en commençant par les colonnes ID / Key et une seule colonne de données.

Suppression des champs d'incrémentation automatique supplémentaires: j'avais un identifiant d'incrémentation automatique sur BaseEntity et sur l'employeur. J'ai supprimé l'ID d'auto-incrémentation de l'employeur et je viens d'avoir la colonne Employer.BaseEntityID et la clé étrangère dans BaseEntity.BaseEntityID. (cela semble avoir été le coupable, mais j'avais l'impression que cela était permis)

Malheureusement, cela a ensuite entraîné le problème suivant: les classes énumérées dans le cadre de l'entité ne peuvent pas avoir de propriétés de navigation (toutes les propriétés de navigation doivent se trouver sur l'entité de base), de sorte que l'héritage va se révéler inutilisable pour nos besoins.


Réponse populaire

Mon nom est Phani et je travaille dans l'équipe ADO.NET Data Services.

Les méthodes ResolveName et ResolveType vous permettent de personnaliser les informations de type que le client écrit dans la charge utile envoyée au serveur et comment la charge utile de réponse du serveur est matérialisée.

Ils vous aident à résoudre les types sur le client et sont utiles dans de nombreux scénarios. Voici quelques exemples:

  1. La hiérarchie des types d'entités sur le client est différente de celle du serveur.
  2. Les types d'entité exposés par le service participent à l'héritage et vous souhaitez utiliser des types dérivés sur le client.

ResolveName est utilisé pour changer le nom de l'entité que nous avons mis en communication lors d'une requête au serveur.

Considérez ce modèle de données: sur le serveur

public class Employee {
    public int EmployeeID {get;set;}
    public string EmployeeName {get;set;}
}

public class Manager:Employee {
    public List<int> employeesWhoReportToMe {get;set;}
}

Lorsque vous utilisez le client pour travailler avec des instances du type d'entité du responsable, lors de la soumission des modifications au serveur, nous attendons des informations de type dans la charge utile lorsque des entités participent à l'héritage.

context.AddObject("Employees",ManagerInstance ); <-- add manager instance to the employees set.
context.SaveChanges();

Toutefois, lorsque le client sérialise cette charge, il spécifie "Employee" comme nom de type, ce qui n’est pas ce qui est attendu sur le serveur. Par conséquent, vous devez fournir un résolveur de noms sur le client,

context.ResolveName = delegate(Type entityType){
    //do what you have to do to resolve the type to the right type of the entity on the server
    return entityType.FullName;
}

un résolveur de types est utilisé de la même manière.

context.ResolveType = delegate(string entitySetName){
    //do what you have to do to convert the entitysetName to a type that the client understands
    return Type.GetType(entitySetName);
}


Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow