-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Incorrect translation of comparison of current value with owned type default value #30996
Comments
I can confirm I have the exact same issue and as you suggested when I filled all the properties it returned the object instead of null. Is there a workaround until this is fixed? |
I found a workaround that seems to work for me. If we set DoNotAllowNull in AutoMapper config it will always create the new object no matter the values of the properties. Here is what I did: In AutoMapper config add this CreateMap<Location, LocationResponse>()
.ForMember(dest => dest.Address, opt => opt.DoNotAllowNull()) This changes the Expression that AutoMapper generates to this [Microsoft.EntityFrameworkCore.Query.EntityQueryRootExpression]
.AsNoTracking()
.Where(x => !x.IsDeleted && (x.BusinessId == AuthService.GetBusinessIdFromRequestDomain()))
.Select(
dtoLocation => new LocationResponse
{
Name = dtoLocation.Name,
Address = new AddressDetails
{
Country = dtoLocation.Address.Country,
City = dtoLocation.Address.City,
Postcode = dtoLocation.Address.Postcode,
District = dtoLocation.Address.District,
Street = dtoLocation.Address.Street,
StreetNumber = dtoLocation.Address.StreetNumber,
Building = dtoLocation.Address.Building,
Entrance = dtoLocation.Address.Entrance,
Floor = dtoLocation.Address.Floor,
Apartment = dtoLocation.Address.Apartment,
AdditionalInformation = dtoLocation.Address.AdditionalInformation
}
}) |
Note for triage: this is a regression from 6.0. Repro without auto-mapper: #nullable disable
using (var context = new SomeDbContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
context.AddRange(
new Request { Id = 1 },
new Request { Id = 2, Info = new() },
new Request { Id = 3, Info = new() { Number = "1" } },
new Request { Id = 4, Info = new() { Text = "2" } },
new Request { Id = 5, Info = new() { Number = "1", Text = "2" } });
await context.SaveChangesAsync();
}
using (var context = new SomeDbContext())
{
var all = context.Set<Request>().ToList();
foreach (var request in all)
{
Console.WriteLine($"{request.Id}: {(request.Info == null ? "no" : "yes")}");
}
}
using (var context = new SomeDbContext())
{
var all = context
.Set<Request>().Select(
e => new RequestDto
{
Id = e.Id,
Info = e.Info == null
? null
: new RequestInfoDto { Number = e.Info.Number, Text = e.Info.Text }
})
.ToList();
foreach (var request in all)
{
Console.WriteLine($"{request.Id}: {(request.Info == null ? "no" : "yes")}");
}
}
public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Request>();//.Navigation(e => e.Info).IsRequired();
}
}
public class Request
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public RequestInfo Info { get; set; }
}
[Owned]
public class RequestInfo
{
public string Text { get; set; }
public string Number { get; set; }
}
public class RequestDto
{
public int Id { get; set; }
public RequestInfoDto Info { get; set; }
}
public class RequestInfoDto
{
public string Text { get; set; }
public string Number { get; set; }
} Current output:
EF Core 6 output:
|
…with owned type default value In optional dependent table sharing scenario, when comparing the dependent to null we first look for any required properties (at least one of them needs to be null), and if we don't have any required properties we look at optional ones (even though this is somewhat ambiguous). Error was that we did similar check as with required properties (i.e. at least one of them must be non), but what we should be doing is checking that all of them are null. Fixes #30996
…with owned type default value In optional dependent table sharing scenario, when comparing the dependent to null we first look for any required properties (at least one of them needs to be null), and if we don't have any required properties we look at optional ones (even though this is somewhat ambiguous). Error was that we did similar check as with required properties (i.e. at least one of them must be null), but what we should be doing is checking that all of them are null. Fixes #30996
…with owned type default value In optional dependent table sharing scenario, when comparing the dependent to null we first look for any required properties (at least one of them needs to be null), and if we don't have any required properties we look at optional ones (even though this is somewhat ambiguous). Error was that we did similar check as with required properties (i.e. at least one of them must be null), but what we should be doing is checking that all of them are null. Fixes #30996
…with owned type default value (#31714) In optional dependent table sharing scenario, when comparing the dependent to null we first look for any required properties (at least one of them needs to be null), and if we don't have any required properties we look at optional ones (even though this is somewhat ambiguous). Error was that we did similar check as with required properties (i.e. at least one of them must be null), but what we should be doing is checking that all of them are null. Fixes #30996
…with owned type default value In optional dependent table sharing scenario, when comparing the dependent to null we first look for any required properties (at least one of them needs to be null), and if we don't have any required properties we look at optional ones (even though this is somewhat ambiguous). Error was that we did similar check as with required properties (i.e. at least one of them must be null, but what we should be doing is checking that all of them are null. Fixes #30996
reopening for patch |
We have:
Test case:
Entity with Owned property. Map to DTO via "ProjectTo".
The main problem is that the mapping works only in the situation when all the properties are filled in, otherwise the owned property is not mapped. In my opinion, it happens due to the fact that the expression translation
(where the comparison with the empty model is done) checks if all properties of the owned model are filled in instead of checking the filling in of one property, at least.
My example: https://github.com/d-kistanov-parc/EF_Automapper_Error_OwnType/blob/master/ConsoleApp/Program.cs
In other words, when i use ProjectTo method, the following Expression is formed:
EntityFramework translates it into:
I have got a question. Why is there "OR" operator, not "AND" ?
The text was updated successfully, but these errors were encountered: