Как я могу легко преобразовать DataReader для Списка <T>? [дубликат]

Между 2 существует четкое различие. Ограничение на уникальность данных определяет, какая комбинация столбцов должна быть уникальной. Уникальный индекс является просто способом удостовериться, что вышеупомянутое всегда допустимо. Но возможно иметь групповой индекс, поддерживающий ограничение на уникальность данных. (если ограничение допускающее задержку =, Только должно быть допустимым во время фиксации, но позволяется быть поврежденным посреди транзакции)

112
задан Jeremy McGee 7 September 2011 в 15:04
поделиться

3 ответа

Я встречал системы, которые используют отражение и атрибуты в свойствах или полях для сопоставления DataReaders с объектами. (Немного похоже на то, что делает LinqToSql.) Они экономят немного времени при вводе и могут уменьшить количество ошибок при кодировании для DBNull и т. Д. После кэширования сгенерированного кода они могут быть быстрее, чем большинство написанного вручную кода, так что сделайте считайте «большой дорогой», если вы делаете это часто.

См. «Защита отражения в .NET» , где приведен один пример.

Затем вы можете написать код вроде

class CustomerDTO  
{
    [Field("id")]
    public int? CustomerId;

    [Field("name")]
    public string CustomerName;
}

...

using (DataReader reader = ...)
{    
   List<CustomerDTO> customers = reader.AutoMap<CustomerDTO>()
                                    .ToList();
}

(AutoMap (), это метод расширения)


@Stilgar, спасибо за отличный комментарий

Если есть в состоянии вы, вероятно, лучше воспользуетесь NHibernate, EF или Linq to Sql, и т. д. Однако в старом проекте (или по другим (иногда уважительным) причинам, например, «здесь не изобретено», «из-за любви к хранимым процессам» и т. д.) не всегда возможно использовать ORM, поэтому можно использовать более легкую систему. полезно иметь «рукава»

. Если вам каждый раз нужно писать много циклов IDataReader, вы увидите преимущество сокращения количества кодов (и ошибок) без необходимости изменения архитектуры системы вы работаете. Это не значит, что это хорошая архитектура для начала ...

Я предполагаю, что CustomerDTO не выйдет из уровня доступа к данным, а составные объекты и т. Д. Будут созданы уровнем доступа к данным с использованием объектов DTO.


Через несколько лет после того, как я написал этот ответ Dapper вошел в мир .NET, он, вероятно, станет очень хорошей отправной точкой для написания вашего нового AutoMapper, возможно, это полностью избавит вас от необходимости делать это.

50
ответ дан 24 November 2019 в 02:45
поделиться

Я бы предложил написать для этого метод расширения:

public static IEnumerable<T> Select<T>(this IDataReader reader,
                                       Func<IDataReader, T> projection)
{
    while (reader.Read())
    {
        yield return projection(reader);
    }
}

Затем вы можете использовать метод LINQ ToList () , чтобы преобразовать его в List , если хотите, например:

using (IDataReader reader = ...)
{
    List<Customer> customers = reader.Select(r => new Customer {
        CustomerId = r["id"] is DBNull ? null : r["id"].ToString(),
        CustomerName = r["name"] is DBNull ? null : r["name"].ToString() 
    }).ToList();
}

Я бы фактически предложил поместить метод FromDataReader в Customer (или где-то еще):

public static Customer FromDataReader(IDataReader reader) { ... }

В результате останется:

using (IDataReader reader = ...)
{
    List<Customer> customers = reader.Select<Customer>(Customer.FromDataReader)
                                     .ToList();
}

(Я не думаю, что вывод типа сработает в этом случае, но я могу ошибаться ...)

196
ответ дан 24 November 2019 в 02:45
поделиться

Вы не можете просто (напрямую) преобразовать datareader в список.

Вы должны перебрать все элементы в datareader и вставить в список

под кодом примера

using (drOutput)   
{
            System.Collections.Generic.List<CustomerEntity > arrObjects = new System.Collections.Generic.List<CustomerEntity >();        
            int customerId = drOutput.GetOrdinal("customerId ");
            int CustomerName = drOutput.GetOrdinal("CustomerName ");

        while (drOutput.Read())        
        {
            CustomerEntity obj=new CustomerEntity ();
            obj.customerId = (drOutput[customerId ] != Convert.DBNull) ? drOutput[customerId ].ToString() : null;
            obj.CustomerName = (drOutput[CustomerName ] != Convert.DBNull) ? drOutput[CustomerName ].ToString() : null;
            arrObjects .Add(obj);
        }

}
9
ответ дан 24 November 2019 в 02:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: