powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Помогите найти ошибку в Linq запросе
17 сообщений из 17, страница 1 из 1
Помогите найти ошибку в Linq запросе
    #39361632
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем! Пытаюсь освоить LINQ to EF в принципе нравится, но есть засада
простой SQL запрос:

Код: java
1.
2.
3.
4.
select
 SP.ID,
 round(iif(@export = 0, SP.CENA_FSO, SP.CENA_EXP) / coalesce((select first 1 KV.KURS from KURS_VALUT KV join S_VALUT SV on SV.ID = KV.ID_VALUT where SV.N_VALUT_KR = @valut order by KURS_DATE desc), 1.00), 2) CENA
from S_PROD SP




LINQ:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
var export = 0;
var valut = "RUB";         

var list = from sp in sProd
	let maxDate = kursValut.Where(w => w.ID_VALUT.N_VALUT_KR == valut).Max(p => p.KURS_DATE)
	let kurs = (decimal)kursValut.Where(w => w.ID_VALUT.N_VALUT_KR == valut && w.KURS_DATE == maxDate).Max(p => p.KURS)
	select new { 
	   sp.ID,     
	   //CENA = 1.34,
	   //CENA = Math.Round((export == 0 ? sp.CENA_FSO : sp.CENA_EXP) / kurs, 2, MidpointRounding.ToEven),
	   //CENA = ((decimal)(export == 0 ? sp.CENA_FSO : sp.CENA_EXP) / (decimal)d),
	   //CENA = (decimal)(export == 0 ? sp.CENA_FSO : sp.CENA_EXP) / (decimal)d,
	   //CENA = (decimal)0 / (decimal) ku  ,
	   //CENA =  Math.Round((decimal)sp.CENA_FSO / (decimal) ku0, 2),
	   //CENA = sp.CENA_FSO* (decimal)kursParam,
	   CENA =  Math.Round(sp.CENA_FSO,2),     
	};



В общем не могу округлить CENA до двух знаков - в любом из комментированных значений происходит ошибка.
Уже весь мозг сломал:)
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361636
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола Питерский,

забирай из базы значения, округляй на клиенте, с помощью Math.Round, после того как сделаешь ToList()

в целом именно так правильно делать, когда работаешь с LINQ
ещё рекомендуют сортировку тоже делать на клиенте, но не всегда это удобно.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361640
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола Питерский,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
var export = 0;
var valut = "RUB";         

var list = sProd.Select(p => new 
  {
     p.ID,
     kurs = kursValut
        .Where(w => w.ID_VALUT.N_VALUT_KR == valut && w.KURS_DATE == maxDate)
        .Max(p => p.KURS),
     p.CENA_FSO,
     p.CENA_EXP
  })
  .ToList() // ←←←←←←← сначала материализуем, т.е. заберём данные из БД
  // потом всё остальное...
  .Select(p => new
  {
     p.ID,
     CENA = Math.Round((export == 0 ? p.CENA_FSO : p.CENA_EXP) / p.kurs, 2, MidpointRounding.ToEven),
  });
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361642
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt, во как - таких тонкостей почему-то в учебниках нет.

Ок - пытаюсь:
Код: java
1.
2.
3.
           var l = list.ToList();
            foreach (var item in l)
                item.CENA = Math.Round(item.CENA, 2);



Студия сразу ругается что item.CENA только для чтения
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361644
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt, понял, спасибо.

Еще, а почему нельзя так:

Код: php
1.
let kurs = kursValut.Where(w => w.ID_VALUT.N_VALUT_KR == valut).OrderByDescending(o => o.KURS_DATE).Select(p => p.KURS).FirstOrDefault()



Пришлось выкручиваться через 2 let и MAX()
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361654
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола ПитерскийСтудия сразу ругается что item.CENA только для чтения

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


Микола ПитерскийЕще, а почему нельзя так:

нет смысла курс засовывать в подзапрос, он отдельно прекрасно считается, можешь сделать через OrderByDescending, но лучше отдельно, а не внутри запроса. сохрани в переменную и используй дальше.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361656
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt[
нет смысла курс засовывать в подзапрос, он отдельно прекрасно считается, можешь сделать через OrderByDescending, но лучше отдельно, а не внутри запроса. сохрани в переменную и используй дальше.

Да - я все уже сделал, все получилось!
Тут оказывается главное идеология, а ее почему-то ни в одном учебнике не описывают. Вроде как я и изучил LINQ, а пользоваться всеравно не могу без подсказок старших товарищей :)
Большое спасибо!!!
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361747
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще засада - не знаю как вернуть List из метода:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
   public class ValutSiteItem
    {  
        public string N_VALUT_KR { get; set; }
        public string N_VALUT { get; set; } 
    }
    public class ValutSite 
    {       
       public List<ValutSiteItem> Select()
       {
    ...

           var list = from sv in sValut
                      orderby sv.N_VALUT_KR
                      select new { sv.N_VALUT_KR, sv.N_VALUT};                                   

           return list.ToList(); // тут ошибка преобразования 
       }          
...
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361782
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола ПитерскийЕще засада - не знаю как вернуть List из метода:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
   public class ValutSiteItem
    {  
        public string N_VALUT_KR { get; set; }
        public string N_VALUT { get; set; } 
    }
    public class ValutSite 
    {       
       public List<ValutSiteItem> Select()
       {
    ...

           var list = from sv in sValut
                      orderby sv.N_VALUT_KR
                      select new ValutSiteItem() { N_VALUT_KR = sv.N_VALUT_KR,  N_VALUT = sv.N_VALUT};                                   

           return list.ToList(); // тут ошибка преобразования 
       }          
...
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361825
stuffhappens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
buser,

Анонимный тип (коллекцию анонимных типов) из метода вернуть нельзя. Нужно создавать отельный класс, использовать Tuple, или что-то более подходящее.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361851
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stuffhappens, можешь показать как это делать на примере - а то у меня опыт c.net пару месяцев.

Я просто видел как Dapper просто это делает и не думал что pдесь будет засада:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
  public class ValutSiteItem
    {
        public string N_VALUT_KR { get; set; }
        public string N_VALUT { get; set; }
    }

	List<ValutSiteItem> listValutSite = new List<ValutSiteItem>();    

	string sql = "select N_VALUT_KR, N_VALUT from S_VALUT order by 1";

	string connString = WebConfigurationManager.ConnectionStrings["connect"].ConnectionString;

	using (IDbConnection db = new FbConnection(connString))
	{
		listValutSite = db.Query<ValutSiteItem>(sql).ToList();
	}       
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361865
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола Питерский,

.. да прокрутите полученную коллекцию list через foreach и в каждом шаге добавляйте item из коллекции в свой список List<ValutSiteItem> .. заодно можно перед добавлением отформатировать данные, например, строки оттримить, числа округлить (если надо) .. оно, конечно, не так красиво, как через всякие Expression, зато - понятно ...
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39361874
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotik, этож велосипед получается - я думал есть более элегантный способ:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
      List<ValutSiteItem> list_ret = new List<ValutSiteItem>();
    
           foreach (var item in list)
           {
               ValutSiteItem vi = new ValutSiteItem();
               vi.N_VALUT_KR = item.N_VALUT_KR;
               vi.N_VALUT = item.N_VALUT;

               list_ret.Add(vi);
           }

           return list_ret;




У тогоже Dapper+SQL намного меньше кода писать приходится. Думал Linq поможет упростить код - а тут наоборот все получается.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39362015
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола ПитерскийУ тогоже Dapper+SQL намного меньше кода писать приходится. Думал Linq поможет упростить код - а тут наоборот все получается.

Вовсе нет. Тут дело не в LINQ, просто в C# нельзя возвращать анонимные классы, ведь если ты будешь дёргать такой метод, откуда ты знаешь что там возвращается? Строгая типизация, Dapper тут тоже ничем не поможет. Определи свой класс, и вместо new { ... } используй new MyClass { ... }, в остальном тоже самое.

Советую обратить внимание на AutoMapper и проекции (projections), погугли, очень интересные техники, решают и снимают много вопросов.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39362158
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt Определи свой класс, и вместо new { ... } используй new MyClass { ... }, в остальном тоже самое.

Да я бы с радостью - просто данный способ не работает, я уже вроде все варианты проверил:

Код: java
1.
2.
3.
4.
5.
6.
7.
     var list1 = from sv in sValut
                      orderby sv.N_VALUT_KR
                       select new ValutSiteItem { sv.N_VALUT_KR, sv.N_VALUT };

           IEnumerable<ValutSiteItem> list2 = from sv in sValut
                       orderby sv.N_VALUT_KR
                       select new ValutSiteItem { sv.N_VALUT_KR, sv.N_VALUT };




Ошибку дает студия - подчеркивает открывающую фигурную скобку, ошибка:
Невозможно инициализировать тип ValutSiteItem инициализатором коллекции, поскольку он не реализует интерфейс System.Collections.IEnumerable
Пытался также наследовать свой класс от интерфейса IEnumerable - но тут видать знаний не хватило.
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39362171
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Микола Питерскийподчеркивает открывающую фигурную скобкуНу основы синтаксиса языка-то стоит выучить

Код: c#
1.
new ValutSiteItem { N_VALUT_KR = sv.N_VALUT_KR, N_VALUT = sv.N_VALUT };
...
Рейтинг: 0 / 0
Помогите найти ошибку в Linq запросе
    #39362175
Микола Питерский
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro, ты опередил - да в этом и была проблема. Спасибо за замечание, язык буду учить.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Помогите найти ошибку в Linq запросе
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]