RavenDb Странное поведение с объектами с элементами равенства - PullRequest
0 голосов
/ 30 января 2012

Я докопался до странной ошибки (в моем коде), когда пытался сохранить список объектов в ravendb. Проблема заключалась в том, что сохраняемый объект имеет члены равенства, сгенерированные resharper. Рассматриваемый объект выглядит следующим образом (обратите внимание, что я закомментировал членов равенства для решения проблемы) -

//[DataContract(Namespace = "")]
//[KnownType(typeof(IApplicationEntity))]
public class ApplicationEntity: IApplicationEntity
{

    public ApplicationEntity()
    {

    }
    public ApplicationEntity(string processName)
    {
        ProcessName = processName;
        Id = "Processes/" + ProcessName;
    }

    public ApplicationEntity(string key, string processName)
    {
        ProcessName = processName;
        Key = key;
        Id = string.Format("Processes/{0}_{1}", Key, ProcessName);

    }


    //[DataMember]
    public string Id { get; set; }
    //[DataMember]
    public string Key { get; set; }
    //[DataMember]
    public string ProcessName { get; set; }
    //[DataMember]
    public string ProcessDescription { get; set; }
    /// <summary>
    /// used to generate sequential unique activity ID generation only.
    /// </summary>
    //[DataMember]
    public string ActivityCount { get; set; }

    //public bool Equals(ApplicationEntity other)
    //{
    //    if (ReferenceEquals(null, other)) return false;
    //    if (ReferenceEquals(this, other)) return true;
    //    return Equals(other.ProcessName, ProcessName);
    //}

    //public override bool Equals(object obj)
    //{
    //    if (ReferenceEquals(null, obj)) return false;
    //    if (ReferenceEquals(this, obj)) return true;
    //    if (obj.GetType() != typeof (ApplicationEntity)) return false;
    //    return Equals((ApplicationEntity) obj);
    //}

    //public override int GetHashCode()
    //{
    //    return (ProcessName != null ? ProcessName.GetHashCode() : 0);
    //}
}

Теперь, если я сохранил объект с реализацией членов равенства, следующий код даст странные результаты -

int count = 0;
        using (var session = _store.OpenSession(_databaseName))
        {


            foreach (var applicationEntity in _listOfApplications)
            {
                var entity = new ApplicationEntity(count.ToString(), applicationEntity.ProcessName);


                //ravenRepositoryCachable.Add(entity);
                session.Store(entity);


                count++;


            }

            session.SaveChanges();
        }

Странное поведение в том, что я ожидаю, что поле Key будет увеличиваться до 400, так как список содержит 400 членов, но вместо этого ключ для первых 10 сохраненных объектов является правильным, то есть от 0 до 9. но 11-е началось с 0 снова и так далее.

но если я закомментирую членов равенства (как в приведенном выше фрагменте кода), то эта проблема исчезнет.

Также, если я добавляю объекты по одному, а не пакетно, проблема исчезает -

int count = 0;
        foreach (var applicationEntity in _listOfApplications)
        {
            using (var session = _store.OpenSession(_databaseName))
            {
                var entity = new ApplicationEntity(count.ToString(), applicationEntity.ProcessName);


                //ravenRepositoryCachable.Add(entity);
                session.Store(entity);
                session.SaveChanges();

                count++;

            }
        }

Я знаю, что решил проблему, но не понимаю, что здесь произошло и почему было затронуто только ключевое поле? Это неопределенное поведение, и я волнуюсь так же, как код должен быть развернут в производстве! Ясно, что члены равенства не должны быть определены. Мне нужно докопаться до этого, это ошибка?

1 Ответ

0 голосов
/ 30 января 2012

Нет, я не думаю, что есть такая ошибка в RavenDB.Вместо этого, я предполагаю, что есть другая проблема с вашим кодом, потому что этот тест (который основан на вашем примере выше) работает для меня:

public class EqualityMembersInSessionCache
{
    public class ApplicationEntity
    {
        public ApplicationEntity(string key, string processName)
        {
            ProcessName = processName;
            Key = key;
            Id = string.Format("Processes/{0}_{1}", Key, ProcessName);
        }


        public string Id { get; set; }
        public string Key { get; set; }
        public string ProcessName { get; set; }


        public bool Equals(ApplicationEntity other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.ProcessName, ProcessName);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(ApplicationEntity)) return false;
            return Equals((ApplicationEntity)obj);
        }

        public override int GetHashCode()
        {
            return (ProcessName != null ? ProcessName.GetHashCode() : 0);
        }
    }

    [Fact]
    public void Has_correct_behaviour()
    {
        var randomNames = new List<string>();
        for (int c = 1; c < 100; c++)
        {
            randomNames.Add(string.Format("test{0}", c));
        }

        using (var store = new EmbeddableDocumentStore { RunInMemory = true })
        {
            int count = 0;
            using (var session = store.OpenSession())
            {
                foreach (var name in randomNames)
                {
                    session.Store(new ApplicationEntity(count.ToString(), name));
                    count++;
                }
                session.SaveChanges();
            }

            using (var session = store.OpenSession())
            {
                var results = session.Query<ApplicationEntity>()
                    .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
                    .ToList();

                Assert.NotEmpty(results);
                Assert.Equal(99, results.Count);
                for (int c = 0; c < 99; c++)
                {
                    Assert.Equal(c, int.Parse(results[c].Key));
                }
            }
        }
    }
}

Если вы хотите, чтобы мы провели дальнейшие исследования по этому вопросу, пожалуйста, предоставьтепровальный тест.

...