How to popular a model from a Datareader in C#?

Asked

Viewed 199 times

6

I’m sorry I was so ignorant about that question. In PHP there was the possibility of using the "Fetchclass" of PDO that took all the results of a table and threw them in an object of a certain class, but I did not find anything similar in C#.

By Datareader I would have to take each property and play in the model manually, what I wanted to do is that it was automatic, since the table names are equal to the model.

At the moment I found the Entity Framework very advanced and would like to understand some lower concepts of . NET before proceeding.

Would be popular a model from a Datareader or Dataset?

  • 1

    I don’t know a way to map the return of the transaction to an object automagically. You would have to either build an extension that did that, or use an ORM. You could use Reflection, but if you found the advanced EF, it will get a little more complicated.

  • Thanks for the @Aline suggestion - I found Dapper and drafted an answer about it.

2 answers

5


No. Automatically no way.

One option is to use a little bit of Reflection and do this job. I’m not going to post an answer with that because it doesn’t seem to me the purpose of this question, mainly because of this part

At the moment I found the Entity Framework very advanced and would like to understand some lower concepts of . NET before proceeding.

What you can do, is create a method that accepts a IDataRecord and return an instance of the model.

For example:

public class Pessoa
{
    public int Id { get; set; }
    public string Nome { get; set; }

    public Pessoa Criar(IDataRecord record)
    {            
        return new Pessoa
        {
           Id = record["id"],
           Nome = record["nome"]
        };
    }
}

From this, you can create a generic method that reads the DataReader and return a data collection.

public IEnumerable<T> LerDados<T>(IDataReader reader, Func<IDataRecord, T> CriarObj)
{
    try
    {
        while (reader.Read())
        {
            yield return CriarObj(reader);
        }
    }
    finally
    {
         reader.Dispose();
    }
}

The use would be something like that

var pessoas = LerDados(dataReader, Pessoa.Criar);

0

As the LINQ user answered, directly is not possible.

However using Aline’s suggestion to use a found ORM, the package "Dapper" and "Dapper.Contrib", which are extremely simple and do not require many settings. To map objects is excellent, even if you don’t like to use a ORM, as it allows you to use your queries in the traditional way.

Example of use:

public class Cidade
{
    public int Id { get; set; }
    public string Nome { get; set; }
    public string Uf { get; set; }
    public int Ativo { get; set; }
}

And here is where we map the result of any Query (example).

List<Cidade> listCidades;
Cidade model = new Cidade { Nome = "São Paulo" };

using (MySqlConnection con = new MySqlConnection(Config.GetConString()))
{
    con.Open();

    var cidades = con.Query<Cidade>
    (
        "SELECT * FROM cidades WHERE nome LIKE @nome",

        new
        {
            nome = "%" + model.Nome + "%"
        }
    );

    listCidades = cidades.ToList<Cidade>();

    con.Close();
}

For simpler queries for Insert, update, delete, you can use Dapper extensions.

T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

In this example I used Mysql and Dapper worked perfectly.

You can also use the Repository standard to group these queries into their proper classes and save generic operations using a generic repository.

public abstract class RepositoryBase<T> where T : class
{
    protected MySqlConnection con;

    protected int timeout;

    public RepositoryBase(MySqlConnection con, int timeout = 10)
    {
        this.con = con;
        this.timeout = timeout;
    }

    public long Insert(T model)
    {
        return con.Insert<T>(model);
    }

    public bool Update(T model)
    {
        return con.Update<T>(model);
    }

    public bool Delete(T model)
    {
        return con.Delete<T>(model);
    }
}

And for the child classes.

public class CidadesRepository : RepositoryBase<Cidade>
{
    public CidadesRepository(MySqlConnection con, int timeout = 10) : base(con, timeout) {}

    public List<Cidade> Search(Cidade model)
    {

        var cidades = con.Query<Cidade>
        (
            "SELECT * FROM cidades WHERE nome LIKE @nome OR uf LIKE @uf",

            new
            {
                nome = "%" + model.Nome + "%",
                uf = "%" + model.Uf + "%"
            }
        );

        return cidades.ToList<Cidade>();
    }
}

Remember that after installing the packages via Nu-Get it is necessary to include the references in the code and in the project.

using Dapper;
using Dapper.Contrib.Extensions;

Dapper: https://github.com/StackExchange/Dapper

Browser other questions tagged

You are not signed in. Login or sign up in order to post.