Присоединиться / Где с LINQ и Lambda

Это происходит потому, что ModelForm не принимает ключевое слово queryset.

Возможно, вы можете достичь этого, установив запрос на представление:

form = IngredienceForm()
form.fields["category"].queryset = 
        IngredienceCategory.objects.filter(user=request.user)

См. соответствующий вопрос здесь .

399
задан BartoszKP 3 July 2018 в 08:00
поделиться

3 ответа

Я нахожу, что если вы знакомы с синтаксисом SQL, то использование синтаксиса запросов LINQ намного понятнее, естественнее и позволяет легче обнаружить ошибки:

var id = 1;
var query =
   from post in database.Posts
   join meta in database.Post_Metas on post.ID equals meta.Post_ID
   where post.ID == id
   select new { Post = post, Meta = meta };

Если вы действительно застряли на использовании ламбд, то ваш синтаксис немного не тот. Вот тот же запрос с использованием методов расширения LINQ:

var id = 1;
var query = database.Posts    // your starting point - table in the "from" statement
   .Join(database.Post_Metas, // the source table of the inner join
      post => post.ID,        // Select the primary key (the first part of the "on" clause in an sql "join" statement)
      meta => meta.Post_ID,   // Select the foreign key (the second part of the "on" clause)
      (post, meta) => new { Post = post, Meta = meta }) // selection
   .Where(postAndMeta => postAndMeta.Post.ID == id);    // where statement
962
ответ дан 22 November 2019 в 23:24
поделиться

С этим можно пойти двумя путями. Используя LINQPad (бесценно, если вы новичок в LINQ) и фиктивную базу данных, я построил следующие запросы:

Posts.Join(
    Post_metas,
    post => post.Post_id,
    meta => meta.Post_id,
    (post, meta) => new { Post = post, Meta = meta }
)

или

from p in Posts
join pm in Post_metas on p.Post_id equals pm.Post_id
select new { Post = p, Meta = pm }

В этом конкретном случае я думаю, что синтаксис LINQ чище (я переключение между ними в зависимости от того, что легче всего читать).

Однако я хотел бы отметить, что если у вас есть соответствующие внешние ключи в вашей базе данных (между post и post_meta), вам, вероятно, не понадобится явное соединение, если вы не пытаетесь загрузить большой количество записей. Ваш пример, похоже, указывает на то, что вы пытаетесь загрузить одно сообщение и его метаданные. Предполагая, что для каждого сообщения существует много записей post_meta, вы можете сделать следующее:

var post = Posts.Single(p => p.ID == 1);
var metas = post.Post_metas.ToList();

Если вы хотите избежать проблемы n + 1, вы можете явно указать LINQ to SQL загрузить все связанные элементы за один раз. (хотя это может быть сложной темой, если вы больше знакомы с L2S). В приведенном ниже примере говорится: «когда вы загружаете сообщение, также загружайте все связанные с ним записи через внешний ключ, представленный свойством Post_metas»:

var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(p => p.Post_metas);

var dataContext = new MyDataContext();
dataContext.LoadOptions = dataLoadOptions;

var post = Posts.Single(p => p.ID == 1); // Post_metas loaded automagically

Можно сделать много вызовов LoadWith на одном наборе DataLoadOptions для одного или нескольких разных типов. Если вы делаете это много, возможно, вам стоит подумать о кешировании.

74
ответ дан 22 November 2019 в 23:24
поделиться

Ваши селекторы ключей неверны. Они должны принимать объект типа рассматриваемой таблицы и возвращать ключ для использования в соединении. Я думаю, вы имеете в виду следующее:

var query = database.Posts.Join(database.Post_Metas,
                                post => post.ID,
                                meta => meta.Post_ID,
                                (post, meta) => new { Post = post, Meta = meta });

Вы можете применить предложение where после, а не как часть селектора ключей.

34
ответ дан 22 November 2019 в 23:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: