代码之家  ›  专栏  ›  技术社区  ›  Andrew_STOP_RU_WAR_IN_UA

领域的过滤器和.NET中keywod之间的用法

  •  0
  • Andrew_STOP_RU_WAR_IN_UA  · 技术社区  · 6 年前
    public class Quest : RealmObject
    {
        [PrimaryKey]
        public string Id { get; set; } = Guid.NewGuid().ToString();
    
        public DateTimeOffset StartDate { get; set; }
        public DateTimeOffset EndDate { get; set; }
    
        public string Name { get; set; }
    
        public int MaxRepeats { get; set; } 
    
        [Backlink(nameof(HistoryItem.Quest))]
        public IQueryable<HistoryItem> HistoryItems{ get; }       
    }
    
    public class HistoryItem : RealmObject
    {
        [PrimaryKey]
        public string Id { get; set; } = Guid.NewGuid().ToString();
    
        public DateTimeOffset DoneTime { get; set; }
    
        public Quest Quest { get; set; }
    }
    

    我需要的是:

    1. 在1天日期范围内筛选
    2. 保留所有maxrepeats==0+的任务,过滤已完成的剩余任务<maxrepeats
    3. 保留所有maxRepeatsPerMonth==0+的任务,过滤已完成的剩余任务<maxRepeatsPerMonth --问题

    我当前的代码是:

    private IQueryable<Quest> SearchQuery(DateTime day)
    {
        var dayStart = day.AddMilliseconds(-100);
        var dayEnd = day.AddHours(24).AddMilliseconds(100);
    
        var monthStart = day.Date.AddDays(-day.Day +1).AddMilliseconds(-100);
            int daysInMonth = DateTime.DaysInMonth(day.Year, day.Month);
        var monthEnd = monthStart.AddDays(daysInMonth).AddMilliseconds(200);
    
        return _db.Realm.All<Quest>().Where(a => a.StartDate < dayStart &&
                                                 a.EndDate > dayEnd) // done 1
                                  .Filter("MaxRepeats == 0 OR HistoryItems.@count <= MaxRepeats") // done 2
                                  .Filter("MaxRepeatsPerMonth == 0 OR (HistoryItems.DoneTime BETWEEN {%@, %@}).@count <= MaxRepeatsPerMonth"); //an Issue
    }
    

    我已经找到了Swift的解决方案(所有语言的过滤器语法都是相同的)。但不可能写

    _db.Realm.All<HistoryItem>().Filter("DoneTime BETWEEN {%@, %@}", date1, date2);
    

    as筛选器在.NET中只有一个输入参数

    我不能写:

    _db.Realm.All<HistoryItem>().Filter("DoneTime BETWEEN {"+ date1+","+ date2 + "}");
    

    在这种情况下,日期将以另一种日期时间格式写入,而不是filter()方法所需的格式。

    另外,我不能使用where()方法,因为它有限制,而且我不能在其中使用count()。(我只能在reaml事务中使用count(),但在我的情况下这样做是错误的)。

    所以…如何在.NET中使用领域的筛选器?

    2 回复  |  直到 6 年前
        1
  •  0
  •   IdontKnowMyName    6 年前

    您可以设置日期格式,例如 outputDate.ToString("yyyy-MM-dd")

    https://docs.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tostring?view=netframework-4.7.2#System_DateTimeOffset_ToString_System_String_


    编辑

    而不是 Filter 使用 Where

    https://realm.io/docs/dotnet/latest/#queries

    _db.Realm.All<Quest>().Where(a => a.StartDate < dayStart && a.EndDate > dayEnd)
        .Where(x => x.MaxRepeats == 0 || x.HistoryItems.Count() <= x.MaxRepeats)
        .Where(x => MaxRepeatsPerMonth == 0 ||
                    x.HistoryItems.Count(q => q.DoneTime >= date1 && q.DoneTime <= date2) <= MaxRepeatsPerMonth);
    
        2
  •  0
  •   Andrew_STOP_RU_WAR_IN_UA    6 年前
    1. 即使在编写的文档中,领域过滤器的语法对于所有语言都是相同的。-- 这不是真的

    2. BETWEEN 领域的.NET实现中不支持关键字。(最新版本--3.3.0。将来可能会支持,但现在不支持)

    3. 当前根本不支持将值替换为.NET的筛选器谓词

    4. 替代方案 之间 对于.NET是:

    .

    .Filter($"HistoryItems.DoneTime >= {monthStartStr} && HistoryItems.DoneTime <= {monthEndStr}");
    

    所以我的问题是:

    .Filter($"MaxRepeatsPerMonth == 0 OR SUBQUERY(HistoryItems, $hi, $hi.DoneTime >= {monthStartStr} && $hi.DoneTime <= {monthEndStr}).@count <= MaxRepeatsPerMonth");