Добавить запись в коллекцию List<> из метода класса. net5

Есть классы.

   public class employee
    {
        public int id;
        public string Name;
    }

  public class Job
    {
        public int id;
        public string JobName;
    }

Они разные и их много. Объявляем их как list

  List<employee> dtemployee = new List<employee>();
  List<Job> dtJob = new List<Job>();

Заполнить их можно, например, так (это работает):

  dtemployee.Add(new employee { id = 1, Name = "Тестовый employee" ); 

Но мне нужно его заполнить из метода другого класса. Причём в качестве параметра передать list можем передать employee, а можем job. Ну и еще много других. Пишем класс, в который передаем этот IList:

        public class dbEngine
        {
            public fill(IList table ,string con, string command)
            {
                var x = new table(); //ошибка  Не знаю как правильно сделать
                table.Add(x);
            }
        }

Вызов предполагается такой.

dbEngine db = new dbEngine();
db.fill(dtemployee,con,"Select * from employee");
db.fill(dtJob,con,"Select * from job");

В общем проблема - как создать запись и добавить в список из класса dbEngine, учитывая, что там разные классы. Подскажите, как правильно создать запись и ее добавить? Пусть пустую. Я не знаю, какой класс будет передан. Нужно это как-то определить. Как? С Property как передать параметры в зависимости от имени я представляю.

Задача будет такая. Я должен написать универсальный метод, который будет делать select из базы данных и заполнять нужные коллекции.

Сторонние фреймоврки не применять.

Спасибо.


Ответы (1 шт):

Автор решения: Alexander Petrov

Такие "универсальные" методы получения данных из БД обычно создают больше проблем чем решают. Тем не менее, я отвечу. С одновременной правкой именования, стиля и пр.

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Job
{
    public int Id { get; set; }
    public string JobName { get; set; }
}
public class DbEngine
{
    private readonly string _connectionString = "...";

    public void Fill<T>(IList<T> list, string command, Func<SqlDataReader, T> func)
    {
        using (var con = new SqlConnection(_connectionString))
        {
            con.Open();
            using (var cmd = new SqlCommand(command, con))
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    var item = func(reader);
                    list.Add(item);
                }
            }
        }
    }
}

Использование:

var employees = new List<Employee>();
var jobs = new List<Job>();

DbEngine db = new DbEngine();

db.Fill(employees, "Select [id], [name] from employee",
    reader => new Employee { Id = reader.GetInt32(0), Name = reader.GetString(1) });

db.Fill(jobs, "Select [id], [name] from job",
    reader => new Job { Id = reader.GetInt32(0), JobName = reader.GetString(1) });

Так как классы Employee и Job не имеют общего предка, мы не можем легко создавать их экземпляры внутри метода Fill. Конечно, это можно сделать с помощью рефлексии, но это будет медленно и склонно к ошибкам.

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


Если сущности имеют одинаковый набор похожих свойств, то можно выделить их в интерфейс (или базовый класс).

public interface IEntity
{
    int Id { get; set; }
    string Name { get; set; }
}
public class Employee : IEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Job : IEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public void Fill<T>(IList<T> list, string command)
    where T : IEntity, new()
{
    using (var con = new SqlConnection(_connectionString))
    {
        con.Open();
        using (var cmd = new SqlCommand(command, con))
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                var item = new T();
                item.Id = reader.GetInt32(0);
                item.Name = reader.GetString(1);
                list.Add(item);
            }
        }
    }
}

В этом случае вызов метода становится проще:

db.Fill(employees, "Select [id], [name] from employee");

db.Fill(jobs, "Select [id], [name] from job");
→ Ссылка