簡體   English   中英

IQueryable-為什么此邏輯失敗?

[英]IQueryable - Why does this logic fail?

我有一個包含多個表的數據庫,在這種情況下,相關的表是

志願者注冊和計划事件:

CREATE TABLE [dbo].[VolunteerSignups] (
    [EventId]      INT            IDENTITY (1, 1) NOT NULL,
    [VolunteerNum] INT            NOT NULL,
    [UserId]       NVARCHAR (128) NULL,
    CONSTRAINT [PK_dbo.VolunteerSignups] PRIMARY KEY CLUSTERED ([EventId] ASC, [VolunteerNum] ASC),
    CONSTRAINT [FK_VolunteerSignups_ProgramEvents_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE SET NULL ON UPDATE CASCADE,
    CONSTRAINT [FK_VolunteerSignups_ProgramEvents_EventId] FOREIGN KEY ([EventId]) REFERENCES [dbo].[ProgramEvents] ([EventId])
);
--Triggers and other unneeded info

CREATE TABLE [dbo].[ProgramEvents] (
    [EventId]            INT            IDENTITY (1, 1) NOT NULL,
    [EventTitle]         NVARCHAR (256) NOT NULL,
    [NumVolunteers]      INT            NOT NULL,
    [EventLocation]      NVARCHAR (512) NOT NULL,
    [ServiceDescription] NVARCHAR (MAX) NOT NULL,
    [StartTime]          DATETIME       NOT NULL,
    [EndTime]            DATETIME       NOT NULL,
    CONSTRAINT [PK_dbo.ProgramEvents] PRIMARY KEY CLUSTERED ([EventId] ASC)
);
--Triggers and other unneeded info

總的來說,我所擁有的是一個簡單的Web應用程序,它允許進行活動(每個活動可能需要1到N名志願者),並且志願者可以報名參加這些活動。 當然,限制是志願者不能兩次報名參加同一活動,並且他們不能報名參加重疊(按時間)的活動。

我幾乎完成了MVC應用程序中的所有其他工作,除了志願者位置要求的后半部分。 我對此有些掙扎,感到惱火,所以我把它留在了最后,而不是讓它延遲了整個項目。 但是現在我不能再拖延了,因為除此查詢外,其他所有方法都有效。

到目前為止,我有:

[Authorize( Roles = "Administrator, Volunteer" )]
public class VolunteerSignupsController : Controller
{
    private EntitiesDb db = new EntitiesDb();

    // GET: VolunteerSignups
    public async Task<ActionResult> Index()
    {
        var uid = User.Identity.GetUserId();
        var exclude = ( db.VolunteerSignups.Where( o => o.UserId == uid ) );

        var volunteerSignups = db.VolunteerSignups.Include( v => v.AspNetUser ).Include( v => v.ProgramEvent );
        var diff = volunteerSignups.Where( u => ( !exclude.Any( p => p.EventId == u.EventId ) ) && u.UserId == null );

        return View( await diff.ToListAsync() );
    }

此代碼可以完美地檢索用戶尚未注冊的事件。 問題在於,它們在注冊事件后會返回重疊事件。 因此,我將代碼修改為以下內容:

[Authorize( Roles = "Administrator, Volunteer" )]
public class VolunteerSignupsController : Controller
{
    private EntitiesDb db = new EntitiesDb();

    // GET: VolunteerSignups
    public async Task<ActionResult> Index()
    {
        ApplicationDbContext db1 = new ApplicationDbContext();

        var uid = User.Identity.GetUserId();
        var exclude = ( db.VolunteerSignups.Where( o => o.UserId == uid ) );

        var volunteerSignups = db.VolunteerSignups.Include( v => v.AspNetUser ).Include( v => v.ProgramEvent );
        var diff = volunteerSignups.Where( u => ( !exclude.Any( p => p.EventId == u.EventId ) ) && u.UserId == null );

        //GET: ProgramEvents that user has already signed up for
        var alreadyVolunteeredFor = db.ProgramEvents.Where( i => exclude.Any( u => i.EventId == u.EventId ) );

        //GET: ProgramEvents that the user has not signed up for 
        var qualifiesFor = db.ProgramEvents.Where( i => diff.Any( u => i.EventId == u.EventId ) );

        /*Get: VolunteerSignups where the ProgramEvent is one where:
               -The user has not previously volunteered
               -The user has not previously volunteered for a different event where the time overlaps with an event they have not signed up for*/
        var intersect = db.VolunteerSignups.Where( i => ( diff.Any( d => ( d.EventId == i.EventId ) &&
            !qualifiesFor.Any( q => q.EventId == i.EventId &&
             alreadyVolunteeredFor.Any( a => a.EventId == i.EventId &&
               a.EndTime.CompareTo( q.StartTime ) >= 0  &&
               a.StartTime.CompareTo( q.EndTime ) <= 0  ) ) ) ) );

        return View( await intersect.ToListAsync() );
    }

我很確定邏輯失敗在於構成intersect的lambda表達式。 在編寫過程中,它只返回diff之前所做的完全相同的事情。 但是,我對此所做的任何更改似乎都從列表中刪除了所有內容。

編輯以回復mjwillis評論:

diff的數據將是VolunteerSignups行,這些行不會為用戶未自願參與的事件填充。 列是
1. xyz 1 null

2. xyz 2 null

3. abc 1 null

qualifiesFor應與ProgramEvents具有相同的行EventId作為條目diff
1. xyz "First Title" 2 "Some Location" "A Description" "11/1/2020 4:00pm" "11/1/2020 7:00pm"
2. abc "Second Title" 1 "A Location" "Some Description" "11/1/2020 5:00pm" "11/1/2020 6:00pm"

alreadyVonteeredFor應符合ProgramEvents排人已自願參加,沒有任何的EventId列應該等於海誓山盟,也不應該是如果任何diffqualifiesFor

  1. dsd "Already Volunteered" 1 "Some Place" "Time overlaps" "11/1/2020 3:00pm" "11/1/2020 4:30pm"

我需要的是intersect僅包含diff行3,因為第1行和第2行對應於時間與志願者已附着的事件重疊的事件。

我找到了解決方案。 問題在於intersect lambda中的a => a.EventId == i.EventId && 那是胡說八道,我也不知道為什么會在那兒。 在沒有alreadyVolunteeredFor將是qualifiesFor和沒有的EventId列將是它的。

正確的答案最終是將intersect的聲明更改為:

var intersect = db.VolunteerSignups.Where( i => ( diff.Any( d => ( d.EventId == i.EventId ) &&
            qualifiesFor.Any( q => q.EventId == i.EventId &&
             !alreadyVolunteeredFor.Any( a =>
               (a.EndTime.CompareTo( q.StartTime ) >= 0)  &&
               (a.StartTime.CompareTo( q.EndTime ) <= 0 ) ) ) ) ) );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM