我应该放弃RavenDB的Integer ID吗?

时间:2013-02-27 18:07:09

标签: c#-4.0 indexing ravendb

更新:这里有一个更全面展示问题https://gist.github.com/pauldambra/5051550

的要点

啊,更多更新......如果我将Mailing类的Id属性设为字符串,那么一切正常。我应该放弃整数ID吗?


我有2个模特

public class Mailing
{
    public int Id { get; set; }
    public string Sender { get; set; }
    public string Subject { get; set; }
    public DateTime Created { get; set; }
}

public class Recipient
{
    public Recipient()
    {
        Status = RecipientStatus.Pending;
    }
    public RecipientStatus Status { get; set; }
    public int MailingId { get; set; }
}

在我的主页上,我想抓住最后10封邮件。有他们的收件人数(最终有不同的状态收件人,但......)

我做了以下索引

public class MailingWithRecipientCount : AbstractMultiMapIndexCreationTask<MailingWithRecipientCount.Result>
        {
            public class Result
            {
                public int MailingId { get; set; }
                public string MailingSubject { get; set; }
                public string MailingSender { get; set; }
                public int RecipientCount { get; set; }
            }

            public MailingWithRecipientCount()
            {
                AddMap<Mailing>(mailings => from mailing in mailings
                                                 select new
                                                            {
                                                                MailingId = mailing.Id,
                                                                MailingSender = mailing.Sender,
                                                                MailingSubject = mailing.Subject,
                                                                RecipientCount = 0
                                                            });
                AddMap<Recipient>(recipients => from recipient in recipients
                                                    select new
                                                               {
                                                                   recipient.MailingId,
                                                                   MailingSender = (string) null,
                                                                   MailingSubject = (string)null,
                                                                   RecipientCount = 1
                                                               });
                Reduce = results => from result in results
                                    group result by result.MailingId
                                    into g
                                    select new
                                               {
                                                   MailingId = g.Key,
                                                   MailingSender = g.Select(m => m.MailingSender)
                                                                    .FirstOrDefault(m => m != null),
                                                   MailingSubject = g.Select(m => m.MailingSubject)
                                                                     .FirstOrDefault(m => m != null),
                                                   RecipientCount = g.Sum(r => r.RecipientCount)
                                               };
            }
        }

我使用

查询
public ActionResult Index()
        {
            return View(RavenSession
                        .Query<RavenIndexes.MailingWithRecipientCount.Result, RavenIndexes.MailingWithRecipientCount>()
                        .OrderByDescending(m => m.MailingId)
                        .Take(10)
                        .ToList());
        }

我得到了:

  

System.FormatException:System.FormatException:输入字符串不是   以正确的格式。在System.Number.StringToNumber(String str,   NumberStyles选项,NumberBuffer&amp; number,NumberFormatInfo信息,   Boolean parseDecimal)

任何帮助表示赞赏

1 个答案:

答案 0 :(得分:4)

是的,整数ID很痛苦。这主要是因为Raven总是存储一个完整的字符串文档密钥,你必须考虑何时使用密钥或你自己的id并进行适当的翻译。减少时,还需要对齐int和string数据类型。

让测试通过的最低要求是:

// in the "mailings" map
MailingId = mailing.Id.ToString().Split('/')[1],

// in the reduce
MailingId = g.Key.ToString(),

但是 - 您可以通过将发件人和主题字符串排除在外,使索引变得更小并且表现更好。你可以把它们放入变换中。

这是一个简化的完整索引,可以做同样的事情。

public class MailingWithRecipientCount : AbstractIndexCreationTask<Recipient, MailingWithRecipientCount.Result>
{
    public class Result
    {
        public int MailingId { get; set; }
        public string MailingSubject { get; set; }
        public string MailingSender { get; set; }
        public int RecipientCount { get; set; }
    }

    public MailingWithRecipientCount()
    {
        Map = recipients => from recipient in recipients
                            select new
                            {
                                recipient.MailingId,
                                RecipientCount = 1
                            };

        Reduce = results => from result in results
                            group result by result.MailingId
                            into g
                            select new
                            {
                                MailingId = g.Key,
                                RecipientCount = g.Sum(r => r.RecipientCount)
                            };

        TransformResults = (database, results) =>
                           from result in results
                           let mailing = database.Load<Mailing>("mailings/" + result.MailingId)
                           select new
                           {
                               result.MailingId,
                               MailingSubject = mailing.Subject,
                               MailingSender = mailing.Sender,
                               result.RecipientCount
                           };
    }
}

顺便说一下,你知道RavenDB.Tests.Helpers包吗?它提供了一个简单的基类RavenTestBase,您可以继承它,为您完成大部分的工作。

using (var store = NewDocumentStore())
{
    // now you have an initialized, in-memory, embedded document store.
}

此外 - 您可能不应在单元测试中扫描程序集中的索引。您可能会引入不属于您测试内容的索引。更好的方法是单独创建索引,如下所示:

documentStore.ExecuteIndex(new MailingWithRecipientCount());