Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dictionary inconsistencies between store and patch for enum keys #18131

Open
loraderon opened this issue Feb 14, 2024 · 4 comments · May be fixed by #18530
Open

Dictionary inconsistencies between store and patch for enum keys #18131

loraderon opened this issue Feb 14, 2024 · 4 comments · May be fixed by #18530

Comments

@loraderon
Copy link

loraderon commented Feb 14, 2024

Edit
Store always uses string keys and patch always uses integer keys no matter if SaveEnumsAsIntegers is specified or not.


Store does not store enums as integers for dictionary keys when SaveEnumsAsIntegers is specified.

However, Patch seems to use integrers for dictionary keys which results in inconsistent data.

Test case

void Main()
{
	//Raven.Embedded.EmbeddedServer.Instance.StartServer();
	using var store = Raven.Embedded.EmbeddedServer.Instance
		.GetDocumentStore(new Raven.Embedded.DatabaseOptions("db")
		{
			Conventions = new()
			{
				SaveEnumsAsIntegers = true,
			},
		});
	store.Initialize();

	using var session = store.OpenSession();
	var foo = new Foo
	{
		Days = {
			{ DayOfWeek.Monday, "monday-store" },
		}
	};

	session.Store(foo);
	session.SaveChanges();

	session.Advanced.Patch<Foo, string>(foo.Id, f => f.Days[DayOfWeek.Monday], "monday-patch");
	session.SaveChanges();

	Raven.Embedded.EmbeddedServer.Instance.OpenStudioInBrowser();
}

public class Foo
{
	public string Id { get; set; }

	public Dictionary<DayOfWeek, string> Days { get; set; } = new();
}

Results

image

@ppekrol
Copy link
Member

ppekrol commented Feb 19, 2024

We will take a look. Meanwhile as a workaround you could write your own JsonConverter for that type that contains dictionary.
https://issues.hibernatingrhinos.com/issue/RavenDB-22084/Dictionary-inconsistencies-between-store-and-patch-when-specifying-SaveEnumsAsIntegers
Custom converters (we are using JSON.NET for serialization), can be registered via DocumentConventions.Serialization.CustomizeJsonSerializer (and Deserializer) methods: https://ravendb.net/docs/article-page/6.0/csharp/client-api/configuration/serialization#customizejsonserializer

@loraderon
Copy link
Author

loraderon commented Apr 24, 2024

I also noticed that the enums are not unique even after reduce.

Edit:
Since it affects all enums (not only dictaionry keys) I started a discussion about it #18439


image

This index groups the results by day and spits out all the values.

public class FooIndex : AbstractIndexCreationTask<Foo, FooIndex.Result>
{
	public FooIndex()
	{
		Map = foos =>
			from f in foos
			from day in f.Days
			select new Result
			{
				Day = day.Key,
				Values = new[] { day.Value},
			};
		
		Reduce = results =>
			from result in results
			group result by new { result.Day } into g
			select new Result
			{
				Day = g.Key.Day,
				Values = g.SelectMany(x => x.Values).ToArray()
			};
	}
	
	public class Result
	{
		public DayOfWeek Day { get; set; }
		public string[] Values { get; set; }
	}
}

@ayende
Copy link
Member

ayende commented Apr 25, 2024

For reference, the issue is different: #18439

@loraderon
Copy link
Author

loraderon commented Apr 29, 2024

I just noticed that the value of SaveEnumsAsIntegers does not matter at all. Dictionary enum keys are always stored as strings and patched as integers.

image

public class DictionaryEnumKeysTests : RavenTestDriver
{
    [Fact]
    public void DictionaryEnumKeys()
    {
        using var store = GetDocumentStore();

        using (var session = store.OpenSession())
        {
            var foo = new FooDictionaryEnum
            {
                Days = new() { { DayOfWeek.Monday, "monday-store" } },
            };
            session.Store(foo);

            session.SaveChanges();

            session.Advanced.Patch<FooDictionaryEnum, string>(foo.Id.ToString(), f => f.Days[DayOfWeek.Monday], "monday-patched");

            session.SaveChanges();
        }

        OpenBrowser(store.Urls.First());
        WaitForUserToContinueTheTest(store);
    }

    public class FooDictionaryEnum
    {
        public string Id { get; set; }
        public Dictionary<DayOfWeek, string> Days { get; set; }
    }
}

@loraderon loraderon changed the title Dictionary inconsistencies between store and patch when specifying SaveEnumsAsIntegers Dictionary inconsistencies between store and patch for enum keys Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants