web-dev-qa-db-fra.com

Dapper et types anonymes

Est-il possible d'utiliser des types anonymes avec Dapper?

Je peux voir comment vous pouvez utiliser Dynamic i.e.

connection.Query<dynamic>(blah, blah, blah) 

est-il alors possible de faire un

.Select(p=> new { A, B ,C }) 

ou une variation de cela par la suite?

Modifier

J'ai pensé vous montrer comment j'utilise Dapper en ce moment. J'ai tendance à mettre en cache (en utilisant un InMemoryCache) les données donc je fais juste une grosse requête au début (ce qui est super rapide avec Dapper) puis j'utilise Linq pour tout trier dans mon référentiel.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Common;
using System.Linq;
using Dapper;

namespace SomeNamespace.Data
{
public class DapperDataContext : IDisposable
{
    private readonly string _connectionString;
    private readonly DbProviderFactory _provider;
    private readonly string _providerName;

    public DapperDataContext()
    {
        const string connectionStringName = " DataContextConnectionString";
        _connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
        _providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName;
        _provider = DbProviderFactories.GetFactory(_providerName);
    }

    public IEnumerable<MyDataView> MyData1 { get; private set; }
    public IEnumerable<MyDataView> MyData2 { get; private set; }

    protected string SqlSelectMyTable1Query
    {
        get
        {
            return @"SELECT Id, A, B, C from table1Name";
        }
    }   


protected string SqlSelectMyTable2Query
{
    get
    {
    return @"SELECT Id, A, B, C from table2Name";
    }
    }

    public void Dispose()
    {
    }

    public void Refresh()
    {
        using (var connection = _provider.CreateConnection())
        {
            // blow up if null
            connection.ConnectionString = _connectionString;
            connection.Open();

            var sql = String.Join(" ",
                            new[]
                                {
                                    SqlSelectMyTable1Query,
                                    SqlSelectMyTable2Query
                                });

            using (var multi = connection.QueryMultiple(sql))
            {
                MyData1 = multi.Read<MyDataView>().ToList();
                MyData2 = multi.Read<MyDataView>().ToList();
            }
        }
    }

    public class MyDataView
    {
        public long Id { get; set; }
        public string A { get; set; }
        public string B { get; set; }
        public string C { get; set; }
    }      
}
}

Le InMemoryCache ressemble à ceci

namespace Libs.Web
{
public class InMemoryCache : ICacheService
{
    #region ICacheService Members

    public T Get<T>(string cacheId, Func<T> getItemCallback) where T : class
    {
        var item = HttpRuntime.Cache.Get(cacheId) as T;
        if (item == null)
        {
            item = getItemCallback();
            HttpContext.Current.Cache.Insert(cacheId, item);
        }
        return item;
    }

    public void Clear(string cacheId)
    {
        HttpContext.Current.Cache.Remove(cacheId);
    }

    #endregion
}

public interface ICacheService
{
    T Get<T>(string cacheId, Func<T> getItemCallback) where T : class;
    void Clear(string cacheId);
}
}
31
Peter

Voici une autre solution pour utiliser des types anonymes avec dapper:

public static class DapperExtensions
{
    public static IEnumerable<T> Query<T>(this IDbConnection connection, Func<T> typeBuilder, string sql)
    {
        return connection.Query<T>(sql);
    }
}

et utilisez-le comme ceci:

var data = connection.Query(() => new 
{
    ContactId = default(int),
    Name = default(string),
}, "SELECT ContactId, Name FROM Contact");
21
Guillaume86

Est-il possible d'utiliser des types anonymes avec Dapper?

Bien sûr, voyez le remplacement de requête non générique, il renvoie un IDictionary<string, object> cet objet est un expando qui peut être casté ou accédé avec la notation par points.

Par exemple:

var v = connection.Query("select 1 as a, 2 as b").First(); 
Console.Write("{0} {1}",v.a, v.b) // prints: 1 2

est-il alors possible de faire un .Select

Bien sûr, vous obtenez un IEnumerable<dynamic> ... vous pouvez exécuter tout ce que vous voulez.

39
Sam Saffron

Juste une petite amélioration de la grande solution de Guillaume86:

public static IEnumerable<T> Query<T>(this IDbConnection connection, Func<T> typeBuilder,
    string sql, dynamic param = null, IDbTransaction transaction = null,
    bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
{
    return SqlMapper.Query<T>(connection, sql, param, transaction, buffered,
        commandTimeout, commandType);
}
3
pistipanko