dapper PropInfo Setter pour EntitySet hérité de la référence de classe abstraite est null

.net abstract-class c# dapper reflection

Question

J'essaie de remplacer un problème SQL LINQ 2 méchant par des requêtes épatantes pour améliorer la performance. Ce faisant, je dois assembler un ensemble d'objets différents afin de créer le gros objet requis pour contenir toutes les informations dont j'ai besoin pour les informations ASN.

Le problème actuel que j'ai est avec une classe abstraite Orders, cette classe est implémentée par deux classes séparées, AutionOrder et MerchantOrder, utilisant une propriété discriminante.

Comme je ne peux pas utiliser dapper pour créer un objet qui est une classe abstraite, j'utilise à la place l'une des classes publiques. mais quand il va construire l'objet , il ne parvient pas à l' intérieur de GetSettableProps il est de trouver le bon DeclaringType mais la GetProperty méthode retourne nulle quand elle est à la recherche d'une propriété qui est internal ou est un EntitySet . J'ai essayé de le contourner en utilisant t.BaseType.GetProperty et p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true) sans succès.

objets factices:

Commande

OrderID, Nom, Adresse, RowVersion (interne), Envois (EntitySet), OrderDetails (EntitySet), Client (EntityRef)

Expédition

ShipmentID, OrderID, TrackingNumber

Détails de la commande

OrderDetailID, OrderID, Produit, QTY, Price

Client

CustomerID, Nom,

Pour ce hit SQL particulier, j'essaie de récupérer certaines des mappages de 1 à 1 dont j'ai besoin.

SELECT o. * À partir des commandes comme o joindre jointes comme c sur o.CustomerID = c.CustomerID où o.OrderID dans (1,2,3);

C'est ce que j'utilise pour utiliser Dapper et le laisser faire c'est magique:

using (var connection = new SqlConnection(_ConnectionString))
{
    connection.Open();
    results = connection.Query<MerchantOrder, MerchantCustomer, MerchantOrder>(sql.ToString(),
        (o, c) => { o.Customer = c; return o; },
        splitOn: "CustomerID");
}

Si je change l'ordre pour être une classe publique, ce problème disparaît cependant, mais ce n'est pas un effet secondaire souhaité. Il échoue lorsque vous essayez de définir le propInfo pour RowVersion - basculer cela en public au lieu de résoudre ce problème interne - mais pas désiré. Mais alors, il échoue lorsqu'il essaie de créer les objets Envois pour la commande. Encore une fois, rien de tout cela n'est un problème lorsque Order est une classe publique.

De plus, je fais des requêtes séparées pour insérer plusieurs relations dans une relation, telles que les envois vers les commandes et les commandes vers les commandes, et en normalisant les résultats en un objet de commande approprié. MerchantOrder est à peu près une classe vide sans véritable logique particulière. La différence ici est juste la façon dont nous finissons par trouver le CustomerID qui est extrait avant le hit SQL réel.

J'utilise aussi la dernière version de dapper à partir du 20/12/2011.

J'aime beaucoup Dapper, mais ce problème est de me rendre la tête sur place - alors merci pour votre aide!

Réponse acceptée

C'était un bug qui est maintenant corrigé dans le tronc:

public class AbstractInheritance
    {
        public abstract class Order
        {
            internal int Internal { get; set; }
            protected int Protected { get; set; }
            public int Public { get; set; }

            public int ProtectedVal { get { return Protected; } }
        }

        public class ConcreteOrder : Order
        {
            public int Concrete { get; set; }
        }
    }

    // http://stackoverflow.com/q/8593871
    public void TestAbstractInheritance() 
    {
        var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();

        order.Internal.IsEqualTo(1);
        order.ProtectedVal.IsEqualTo(2);
        order.Public.IsEqualTo(3);
        order.Concrete.IsEqualTo(4);

    }

Une remarque est que, de par leur conception, nous ne définissons pas de champs ou de propriétés privés dans les classes de base. Le comportement peut être magique et non cohérent.

Par exemple:

class A { private int a {get; set;} }
class B : A { private int a {get; set;} } 
class C: B {} 

// What should "select 1 a" do? Set it on A? Set it on B? Set it on Both? Set it on neither?

Nous sommes allés avec "le mettre sur aucun des"


Réponse populaire

Je pense que ce n'est pas possible (à cause de la classe abstraite) sans modifier votre code.

J'ai eu un problème similaire et j'ai fini par créer un nouvel objet privé à l'assemblage où se trouvent mes référentiels dérivés de la classe de base abstraite.

Cette classe n'est pas abstraite et n'est visible que par la classe de référentiel qui stocke les données. Cette classe a toutes les méthodes requises pour la table réelle.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi