Конструкторы сущностей

Последнее обновление: 19.11.2021

Когда EF Core создает объект сущности, например, при после получения данных из БД, он вначале вызывае конструктор по умолчанию, который не имеет параметров, и затем передает каждому свойству полученные из бд значения.

Если EF Core находит конструктор с параметрами, где названия и типы параметров соответствуют устанавливаемым свойствам, то вместо установки свойств EF передает полученные из БД значения параметрам конструктора. При этом между параметрами и свойствами должно быть соответствие по типу и имени за тем исключением, что названия могут отличаться по регистру, например, свойство Name и параметр name. Рассмотрим на примере. Допустим, у нас есть следующая сущность User:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public User(string name, int age)
    {
        Name = name;
        Age = age;
        Console.WriteLine($"Вызов конструктора для объекта {name}");
    }
}

Класс User имеет три свойства и через конструктор устанавливает два из них.

Пусть у нас будет стандартный контекст данных:

public class ApplicationContext : DbContext
{
    public DbSet<User> Users { get; set; } = null!;
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=helloapp.db");
    }
}

И, допустим, в программе создаем несколько объектов User, добавляем их в БД и получаем обратно из БД:

using (ApplicationContext db = new ApplicationContext())
{
	db.Database.EnsureDeleted();
    db.Database.EnsureCreated();
	
    User tom = new User("Tom", 37);
    User bob = new User("Bob", 41);
    db.Users.Add(tom);
    db.Users.Add(bob);
    db.SaveChanges();
}
using (ApplicationContext db = new ApplicationContext())
{
	Console.WriteLine("Получение данных из БД");
    var users = db.Users.ToList();
    foreach(var user in users)
        Console.WriteLine($"{user.Name} - {user.Age}");
}

Здесь при получении данных при выполнении метода db.Users.ToList() EF Core будет вызывать для каждой полученной строки из таблицы объект User, вызывая его конструктор с двумя параметрами. Для наглядности в примере выше разделы операции добавления и получения по разным объектам контекста. В итоге мы получим следующий консольный вывод:

Вызов конструктора для объекта Tom
Вызов конструктора для объекта Bob
Получение данных из БД
Вызов конструктора для объекта Tom
Вызов конструктора для объекта Bob
Tom - 37
Bob - 41

Здесь надо учитывать несколько моментов:

  • Необязательно для всех свойств определять в конструкторе свои параметры. Например, свойство Id не устанавливается в конструкторе. Те свойства, для которых в конструкторе не определено параметров, устанавливаются напрямую, как в общем случае.

  • Параметры и свойства должны соответствовать по имени и типу за исключением регистра имени.

  • Конструкторы могут иметь любой модификатор доступа, в том числе, private.

  • EF Core НЕ устанавливает таким обазом навигационные свойства, которые представляют другие сущности и имеют конструктор:

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public Company? Company { get; set; }
    
        public User(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }
    
    public class Company
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<User> Users { get; set; } = new List<User>();
        public Company(string name) => Name = name;
    }
    

При этом класс может определять несколько конструкторов с разным количеством параметров:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public User(string name)
    {
        Name = name;
        Age = 18;
    }
    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850