Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.8k views
in Technique[技术] by (71.8m points)

c# - Nested DTOs with optional navigation properties: "No coercion operator is defined between types 'Expression[]' and anonymous type"

Im am trying to build a nested DTO with Entity Framework (6.2.0) using navigation properties. The navigation properties are optional, so I need to handle null values in a way that the corresponding property of the DTO is null also:

var result = db.Projects.Select(
    p => new
    {
        p.Id,
        Notifications = p.Notifications
            .Where(n => n.ContactId == user.Id)
            .Select(a => new
            {
                a.Id,
                a.ContactId,
                Candidate = a.Candidate == null ? null : new
                {
                    a.Candidate.Id,
                    a.Candidate.LastName
                }
            })
            .OrderByDescending(n => n.Timestamp)

    })
    .FirstOrDefault(p => p.Id == projectId);

As the code shows, in my model, there are Project entities with 0-n Notifications, where a Notification can optionally have one Candidate.

The above code throws:

System.InvalidOperationException: 'No coercion operator is defined between types 'System.Linq.Expressions.Expression[]' and '<>f__AnonymousType43`2[System.Int32,System.String]'.'

at runtime. If I remove the null check like so

Candidate = new
{
   a.Candidate.Id,
   a.Candidate.LastName
}

it expectedly throws an exception when the Candidate property is null. Null propagation does not work either, and - even if it did - would not meet the requirement that the DTO property Candidate should be null and not an object with null property values:

Candidate = new
{
   Id = a.Candidate?.Id,
   LastName = a.Candidate?.LastName
}

This does not compile:

An expression tree lambda may not contain a null propagating operator.

  • How can I create a nested DTO with optional properties based on (optional) navigation properties?
  • What is considered best practice for this (not so exotic?) requirement?

For reference, the definition of the navigation properties:

modelBuilder.Entity<Project>(entity =>
{
    // ...

    entity.HasMany(p => p.Notifications)
        .WithOne(a => a.Project)
        .HasForeignKey(a => a.ProjectId)
        .IsRequired(false)
        .OnDelete(DeleteBehavior.Cascade);

});

modelBuilder.Entity<Notification>(entity =>
{  
    // ...
 
    entity.HasOne(e => e.Candidate)
        .WithMany(c => c.Notifications)
        .HasForeignKey(e => e.CandidateId)
        .HasPrincipalKey(e => e.Guid)
        .IsRequired(false)
        .OnDelete(DeleteBehavior.SetNull);
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...