Информация об изменениях

Сообщение Re[3]: Локализация и linq от 03.02.2018 18:20

Изменено 04.02.2018 0:42 sergeya

исправил опечатку

Re[3]: Локализация и linq
Здравствуйте, karbofos42, Вы писали:

K>Мне кажется, что как-то так немного получше будет:


BE>>
BE>>            Func<Visit_Reason,string> locReason;
BE>>            
BE>>            ...
BE>>            
BE>>            cBVisitReason.DataSource = (from p in db.Visit_Reason
BE>>                                  where p.IsDeleted == false
BE>>                                  select new
BE>>                                  {
BE>>                                      p.ID,
BE>>                                      Reason = locReason(p)
BE>>                                  }).ToList();
BE>>


В этом случае из БД будут загружены все поля таблицы Visit_Reason.
Т.к. linq провайдеру не известно, какие поля Visit_Reason могут понадобиться внути функции locReason.

Если заменить функцию на выражение, то linq провайдер сможет распарсить его и запросить из БД только нужно поле.

По умолчанию динамическая подстановка выражения в linq невозможна, но существуют сторонние расширения.
Например, с помощью расширения AsExpandable из библиотеки LinqKit (http://www.albahari.com/nutshell/linqkit.aspx) можно сделать так:

BE>>
BE>>            Expr<Func<Visit_Reason,string>> locReason;
BE>>            
BE>>            ...
BE>>            
BE>>            cBVisitReason.DataSource = (from p in db.Visit_Reason.AsExpandable()
BE>>                                  where p.IsDeleted == false
BE>>                                  select new
BE>>                                  {
BE>>                                      p.ID,
BE>>                                      Reason = locReason.Invoke(p)
BE>>                                  }).ToList();
BE>>


Вызов AsExpandable() создает для IQueryable объекта враппер ExpandableQuery. Это враппер выполняет дополнительную трансформацию linq запросов, подставляя вместо внешних вызовов тело исходного выражения.

Если унаследовать все локализуемые таблицы от интерфейса (пусть будет ILocalizedDectionary), то можно будет написать обобщенное выражение и использовать его для всех справочников:

interface ILocalizedDectionary 
{ 
    public string Reason_UA {get;set}
    public string Reason_RU {get;set}
}

class Visit_Reason : ILocalizedDectionary 
{}

class Leave_Reason : ILocalizedDectionary 
{}

Expr<Func<ILocalizedDectionary,string>> locReason;

var visitReasons = (from p in db.Visit_Reason 
                                  select new
                                  {
                                      Reason = locReason(p)
                                  }).ToList();

var leaveReasons = (from p in db.Leave_Reason 
                                  select new
                                  {
                                      Reason = locReason(p)
                                  }).ToList();
Re[3]: Локализация и linq
Здравствуйте, karbofos42, Вы писали:

K>Мне кажется, что как-то так немного получше будет:


BE>>
BE>>            Func<Visit_Reason,string> locReason;
BE>>            
BE>>            ...
BE>>            
BE>>            cBVisitReason.DataSource = (from p in db.Visit_Reason
BE>>                                  where p.IsDeleted == false
BE>>                                  select new
BE>>                                  {
BE>>                                      p.ID,
BE>>                                      Reason = locReason(p)
BE>>                                  }).ToList();
BE>>


В этом случае из БД будут загружены все поля таблицы Visit_Reason.
Т.к. linq провайдеру не известно, какие поля Visit_Reason могут понадобиться внути функции locReason.

Если заменить функцию на выражение, то linq провайдер сможет распарсить его и запросить из БД только нужно поле.

По умолчанию динамическая подстановка выражения в linq невозможна, но существуют сторонние расширения.
Например, с помощью расширения AsExpandable из библиотеки LinqKit (http://www.albahari.com/nutshell/linqkit.aspx) можно сделать так:

BE>>
BE>>            Expr<Func<Visit_Reason,string>> locReason;
BE>>            
BE>>            ...
BE>>            
BE>>            cBVisitReason.DataSource = (from p in db.Visit_Reason.AsExpandable()
BE>>                                  where p.IsDeleted == false
BE>>                                  select new
BE>>                                  {
BE>>                                      p.ID,
BE>>                                      Reason = locReason.Invoke(p)
BE>>                                  }).ToList();
BE>>


Вызов AsExpandable() создает для IQueryable объекта враппер ExpandableQuery. Это враппер выполняет дополнительную трансформацию linq запросов, подставляя вместо внешних вызовов тело исходного выражения.

Если унаследовать все локализуемые таблицы от интерфейса (пусть будет ILocalizedDictionary), то можно будет написать обобщенное выражение и использовать его для всех справочников:

interface ILocalizedDectionary 
{ 
    public string Reason_UA {get;set}
    public string Reason_RU {get;set}
}

class Visit_Reason : ILocalizedDictionary
{}

class Leave_Reason : ILocalizedDictionary
{}

Expr<Func<ILocalizedDictionary,string>> locReason;

var visitReasons = (from p in db.Visit_Reason 
                                  select new
                                  {
                                      Reason = locReason(p)
                                  }).ToList();

var leaveReasons = (from p in db.Leave_Reason 
                                  select new
                                  {
                                      Reason = locReason(p)
                                  }).ToList();