Не могу получить бритвенную страницу много ко многим навигации, чтобы вернуть данные из правой таблицы для сетки кендо - PullRequest
0 голосов
/ 04 апреля 2020

Не уверен, правильно ли я сказал, но у меня есть бизнес-приложение для страниц-бритв в net core 3.1 с довольно большим количеством соединений. Я сейчас работаю над одним объединением и пытаюсь передать результаты в сетку кендо с помощью вызова хранилища. Вот примеры для примера, к которым относятся «Notes» и «NoteTypes», к которым присоединяются «NoteNoteTypeJoins»


public class Note
{
    public int ID { get; set; }
    [Display(Name = "Short Title")]
    [Required]
    public String Title { get; set; }
    [Display(Name = "Note Content")]
    public String NoteText { get; set; }
    public int UserID { get; set; }

        //some fields left out for brevity

    public ICollection<NoteStaffJoin> NoteStaffJoins { get; set; }
    public ICollection<NoteClientJoin> NoteClientJoins { get; set; }
    public ICollection<NoteOrgJoin> NoteOrgJoins { get; set; }
    public ICollection<NoteNoteTypeJoin> NoteNoteTypeJoins { get; set; }

}
public class NoteNoteTypeJoin
{
    public int NoteNoteTypeJoinID { get; set; }
    public int NoteID { get; set; }
    public int NoteTypeID { get; set; }
    public DateTime? Saved { get; set; }
    public int? UserID { get; set; }

    public Note Note { get; set; }
    public NoteType NoteType { get; set; }


}

public class NoteType
{
    public int ID { get; set; }
    public string Type { get; set; }
    public int? ParentID { get; set; }
    public int? NoteTypeGroupID { get; set; }
    public int? DisplayOrder { get; set; }
    public int? UserID { get; set; }

    public ICollection<NoteNoteTypeJoin> NoteNoteTypeJoins { get; set; }

}
public FliveRetryContext(DbContextOptions<FliveRetryContext> options)
    : base(options)
{
    public DbSet<FliveRetry.Models.Note> Note { get; set; }
    public DbSet<FliveRetry.Models.NoteType> NoteType { get; set; }
    public DbSet<FliveRetry.Models.NoteNoteTypeJoin> NoteNoteTypeJoin { get; set; }
}

Внешние ключи и c все правильно определены, насколько я могу видеть по ef core

CREATE TABLE [dbo].[NoteNoteTypeJoin] (
    [NoteNoteTypeJoinID] INT           IDENTITY (1, 1) NOT NULL,
    [NoteID]             INT           NOT NULL,
    [NoteTypeID]         INT           NOT NULL,
    [Saved]              DATETIME2 (7) NULL,
    [UserID]             INT           NULL,
    CONSTRAINT [PK_NoteNoteTypeJoin] PRIMARY KEY CLUSTERED ([NoteNoteTypeJoinID] ASC),
    CONSTRAINT [FK_NoteNoteTypeJoin_Note_NoteID] FOREIGN KEY ([NoteID]) REFERENCES [dbo].[Note] ([ID]) ON DELETE CASCADE,
    CONSTRAINT [FK_NoteNoteTypeJoin_NoteType_NoteTypeID] FOREIGN KEY ([NoteTypeID]) REFERENCES [dbo].[NoteType] ([ID]) ON DELETE CASCADE
);


GO
CREATE NONCLUSTERED INDEX [IX_NoteNoteTypeJoin_NoteID]
    ON [dbo].[NoteNoteTypeJoin]([NoteID] ASC);


GO
CREATE NONCLUSTERED INDEX [IX_NoteNoteTypeJoin_NoteTypeID]
    ON [dbo].[NoteNoteTypeJoin]([NoteTypeID] ASC);


Я пробовал каждый пример в сети за последнюю неделю, но могу ' не понимаю это правильно. В конце концов я заставил это работать, используя идентификатор в таблице соединений, который не должен вызывать таблицу NoteTypes:

public async Task<List<Note>> GetAllNotesForNoteTypeIDAsync(int notetypeid)
        {
            var noteData = await context.Note
                       .Include(n => n.NoteNoteTypeJoins)
                       .ThenInclude(t => t.NoteType)
                       .Where(i => i.NoteNoteTypeJoins.Any(x => x.NoteTypeID == notetypeid))
                       .ToListAsync();

            return noteData;
        }

Мне пришлось добавить этот параметр referenceloophandling в startup.cs, чтобы включить включения в работу В общем, спасибо Telerik за эту информацию:

services.AddRazorPages().AddNewtonsoftJson
                    (options => {
                        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                        options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                    });

Это также работает, опять же, только для запроса левой таблицы, хотя и включает другие:

public async Task<List<Note>> GetAllNotesForUserAsync(int userId)
        {
            var noteData = await context.Note
                      .Include(n => n.NoteNoteTypeJoins)
                      .ThenInclude(t => t.NoteType)
                      .Where(i => i.UserID == userId)
                      .ToListAsync();

            return noteData;
        }

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

public async Task<List<Note>> GetAllNotesForNoteTypeAsync(string notetype)
        {            
            var noteData = await context.Note
                       .Include(n => n.NoteNoteTypeJoins)
                       .ThenInclude(t => t.NoteType)
                       .Where(i => i.NoteNoteTypeJoins.Any(x => x.NoteType.Type.ToString() == notetype))
                       .ToListAsync();
            return noteData;
        }

Это сбой со следующим сообщением:

An unhandled exception occurred while processing the request.
InvalidOperationException: The LINQ expression 'DbSet<NoteNoteTypeJoin>
.Where(n0 => EF.Property<Nullable<int>>((EntityShaperExpression: 
EntityType: Note
ValueBufferExpression: 
(ProjectionBindingExpression: EmptyProjectionMember)
IsNullable: False
), "ID") != null && EF.Property<Nullable<int>>((EntityShaperExpression: 
EntityType: Note
ValueBufferExpression: 
(ProjectionBindingExpression: EmptyProjectionMember)
IsNullable: False
), "ID") == EF.Property<Nullable<int>>(n0, "NoteID"))
.Join(
outer: DbSet<NoteType>, 
inner: n0 => EF.Property<Nullable<int>>(n0, "NoteTypeID"), 
outerKeySelector: n1 => EF.Property<Nullable<int>>(n1, "ID"), 
innerKeySelector: (o, i) => new TransparentIdentifier<NoteNoteTypeJoin, NoteType>(
Outer = o, 
Inner = i
))
.Any(n0 => n0.Inner.Type.ToString() == __notetype_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Я тоже не у меня есть intellisense доступ к последнему соединению, что мешает мне использовать множество предложений на форумах, поэтому что-то вроде .Where (n => n.NoteNoteTypeJoins.Type == notetype)) недоступно, так как .Type недоступен после NoteNoteTypeJoins.

Это четыре, многие, многие отношения, которые мне нужно отфильтровать по:

Note = await _context.Note
.Include(i => i.NoteOrgJoins).ThenInclude(i => i.Org)
.Include(i => i.NoteClientJoins).ThenInclude(i => i.Client)
.Include(i => i.NoteStaffJoins).ThenInclude(i => i.Staff)
.Include(i => i.NoteNoteTypeJoins).ThenInclude(i => i.NoteType)

Если кто-то может предложить рабочий навигационный вызов, а не присоединения, это может избавить меня от неприятностей. По крайней мере, для звонков с типом заметки я буду в восторге. Если вы покажете мне, как добавить и другие звонки, это было бы еще лучше. Я все еще изучаю C# и бритву, так что это может быть что-то вне самого вызова, но я попытался придерживаться стандартной настройки.

Спасибо всем

1 Ответ

0 голосов
/ 06 апреля 2020

У меня также нет доступа к последнему соединению с помощью intellisense, что мешает мне использовать множество предложений на форумах, поэтому что-то вроде .Where (n => n.NoteNoteTypeJoins.Type == notetype)) isn недоступно, поскольку .Type недоступен после NoteNoteTypeJoins.

Причина заключается в том, что неявная оценка клиента была отключена в EF Core 3.

Ссылка:

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq -запросы-не-больше-оцениваются-на-клиенте

Вы можете изменить свой код, как показано ниже:

var noteData = await _context.Note
                   .Include(n => n.NoteNoteTypeJoins)
                   .ThenInclude(t => t.NoteType)                                    
                   .ToListAsync();

var d = noteData.Where(i => i.NoteNoteTypeJoins.Any(x => x.NoteType.Type.ToString() == notetype))
                .ToList();

Другой Дело в том, что свойство Type в вашем классе NoteType является типом строки. Нет необходимости использовать метод ToString():

var noteData = await _context.Note
                   .Include(n => n.NoteNoteTypeJoins)
                   .ThenInclude(t => t.NoteType)
                   .Where(i => i.NoteNoteTypeJoins.Any(x => x.NoteType.Type == notetype))
                   .ToListAsync();
...