Skip to content

Byte array in owned entity mapped to JSON returns different value when using projection #3566

Description

@drapka

Hi, I encountered a problem while working with a byte array in an owned entity mapped to JSON - it looks like the materialization behaves differently when getting the whole entity vs getting only the specific property.
I would like to use this for encrypted columns, below is a simplified example.

Looks similar to dotnet/efcore#33435.

Sample Code

using Microsoft.EntityFrameworkCore;
await using var context = new BloggingContext();
await context.Database.EnsureCreatedAsync();
var blog = new Blog
{
Posts =
[
new Post { Content = "This is the content of the first post."u8.ToArray() }
]
};
await context.Blogs.AddAsync(blog);
await context.SaveChangesAsync();
var blogs1 = await context.Blogs.ToListAsync(); var blogs2 = await context.Blogs
.SelectMany(b => b.Posts.Select(p => p.Content))
.ToListAsync();
var content1 = blogs1[0].Posts[0].Content; var content2 = blogs2[0];
var decodedViaSql = await context.Database
.SqlQueryRaw<byte[]>( "SELECT decode((b.\"Posts\"->0->>'Content'), 'base64') AS \"Value\" FROM \"Blogs\" AS b LIMIT 1")
.FirstAsync();
Console.WriteLine($"content1 len={content1.Length}, bytes={string.Join(",", content1)}"); Console.WriteLine($"content2 len={content2.Length}, bytes={string.Join(",", content2)}"); Console.WriteLine($"decodedViaSql len={decodedViaSql.Length}, bytes={string.Join(",", decodedViaSql)}"); Console.WriteLine("content1 equals content2: " + content1.SequenceEqual(content2)); Console.WriteLine("content1 equals decodedViaSql: " + content1.SequenceEqual(decodedViaSql));
Console.WriteLine("content2 equals decodedViaSql: " + content2.SequenceEqual(decodedViaSql));
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs => Set<Blog>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("Host=localhost;Port=5432;Username=postgres;Password=password;Database=demo");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.OwnsMany<Post>(b => b.Posts, b =>
{
b.ToJson();
b.WithOwner();
});
}
}
public class Blog
{
public int BlogId { get; set; }
public List<Post> Posts { get; set; } = [];
}
public class Post
{
public required byte[] Content { get; set; }
}

Thanks for looking into this.

Versions:
.Net: 9, 10
Npgsql.EntityFrameworkCore.PostgreSQL: v9.0.4, v10.0.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions