Подтвердить что ты не робот

Dapper PropInfo Setter для унаследованного EntitySet из ссылки абстрактного класса имеет значение null

Я пытаюсь заменить неприятный столбец LINQ 2 SQL с помощью некоторых запросов dapper для улучшения производительности. При этом мне нужно сплести кучу разных объектов вместе, чтобы создать большой объект, необходимый для хранения всей необходимой мне информации для ASN-информации.

Текущая проблема, с которой я столкнулась, связана с абстрактным классом Orders, этот класс реализуется двумя отдельными классами AutionOrder и MerchantOrder с использованием свойства дискриминатора.

Так как я не могу использовать dapper для создания объекта, который является абстрактным классом, я вместо этого использую один из открытых классов. однако, когда он идет, чтобы построить объект, он терпит неудачу внутри GetSettableProps, он находит правильный DeclaringType, но метод GetProperty возвращает null, когда он ищет свойство, которое является internal, или является EntitySet. Я попытался взломать его, используя t.BaseType.GetProperty, а также p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true) без успеха.

фиктивные объекты:

Order

OrderID, имя, адрес, RowVersion (внутренний), отправления (EntitySet), OrderDetails (EntitySet), клиент (EntityRef)

Пересылка

Идентификатор доставки, OrderID, TrackingNumber

OrderDetails

OrderDetailID, OrderID, Product, QTY, Price

Клиент

CustomerID, Name,

Для этого конкретного SQL-удара я пытаюсь захватить некоторые из соотношений 1 к 1, которые мне нужны.

SELECT o. * from Orders as o left join Клиенты как c on o.CustomerID = c.CustomerID, где o.OrderID в (1,2,3);

Это то, что я использую, чтобы использовать dapper и позволить ему делать это волшебство:

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

Если я изменил Order на публичный класс, эта проблема исчезнет, ​​но это не является желательным побочным эффектом. Он не работает при попытке установить propInfo для RowVersion - переключая его на лобке, а не на внутреннюю, решив эту проблему - хотя и не желаемый. Но тогда он терпит неудачу, когда он пытается создать объекты "Посылки" для "Заказ". Опять же, это не проблема, когда заказ является публичным классом.

Также я занимаюсь отдельными запросами, чтобы вытащить многие из этих отношений, такие как "Отгрузки в заказы" и "OrderDetails" в "Заказы" и нормализовать результаты в правильный объект "Заказ". MerchantOrder - довольно пустой класс без реальной специальной логики. Различающийся здесь - это то, как мы в конечном итоге находим идентификатор CustomerID, который абстрагируется до фактического ударов SQL в любом случае.

Также я использую последнюю версию dapper по состоянию на 12/20/2011.

Мне очень нравится dapper, но эта проблема делает мою голову асплодированной - так спасибо за помощь!

4b9b3361

Ответ 1

Это была ошибка, которая теперь исправлена ​​в туловище:

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

    }

Одностороннее замечание состоит в том, что по дизайну мы не устанавливаем частные поля или свойства в базовых классах. Поведение может быть волшебным и непротиворечивым.

Например:

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?

Мы пошли с "установить его ни на"

Ответ 2

Я думаю, что это невозможно (из-за абстрактного класса) без изменения вашего кода.

У меня была аналогичная проблема, и я создал новый объект, закрытый для сборки, где у меня есть мои репозитории, которые получены из абстрактного базового класса.

Этот класс не является абстрактным и доступен только для класса репозитория, который хранит данные, у этого класса были все необходимые методы для фактической таблицы.