0

I have following DTO:

public class DTO_UserWithCreds
{
    public string Name { get; set; }

    public string Surname { get; set; }
    public string Ava1 { get; set; }
    public UserType Type { get; set; }
    public string Uid { get; set; }

    public DateTime? BanDateTime { get; set; }
    
    };

And I get users from database as following:

  var users = from vkuser in _context.VkUsers
                join contextUser in _context.Users on vkuser.Uid equals contextUser.Uid
                join userClaim in _context.UserClaims on contextUser.Id equals userClaim.UserId
                let userBanOffset = contextUser.LockoutEnd
                let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : null
                select new DTO_UserWithCreds
                { 
                    Name = vkuser.Name,
                    Surname = vkuser.Surname,
                    Ava1 = vkuser.Ava1,
                    Uid = vkuser.Uid,
                    Type =  DTO_UserWithCreds.FromString(userClaim.ClaimValue),
                    BanDateTime = userBan
                };
       

I get following error message (I dont really understand it to be honest): error desc

If I change request to this:

  var users = from vkuser in _context.VkUsers
                join contextUser in _context.Users on vkuser.Uid equals contextUser.Uid
                join userClaim in _context.UserClaims on contextUser.Id equals userClaim.UserId
                let userBanOffset = contextUser.LockoutEnd
               // let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : null
                select new DTO_UserWithCreds
                { 
                    Name = vkuser.Name,
                    Surname = vkuser.Surname,
                    Ava1 = vkuser.Ava1,
                    Uid = vkuser.Uid,
                    Type =  DTO_UserWithCreds.FromString(userClaim.ClaimValue),
                    BanDateTime = contextUser.LockoutEnd?.DateTime 
                };

I will have compile error that lambda inside expression tree cant contain null propagation operator. Is it possible to get this information like I want? Or I have to write second query?

jps
  • 20,041
  • 15
  • 75
  • 79
Michael Snytko
  • 327
  • 3
  • 13
  • 1
    You might try: `let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : (DateTime?)null`. I often have this problem with nullable `DateTime` in a tertiary operator. It can't figure out what type the `null` is supposed to be, so you have to give it a hint. – Matt Burland Jul 14 '20 at 13:02

4 Answers4

2

You could cast the null to DateTime? :

let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : (DateTime?)null
Mohammed Sajid
  • 4,778
  • 2
  • 15
  • 20
2

You just missed a cast:

  var users = from vkuser in _context.VkUsers
                join contextUser in _context.Users on vkuser.Uid equals contextUser.Uid
                join userClaim in _context.UserClaims on contextUser.Id equals userClaim.UserId
                let userBanOffset = contextUser.LockoutEnd
                let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : (DateTime?)null
                select new DTO_UserWithCreds
                { 
                    Name = vkuser.Name,
                    Surname = vkuser.Surname,
                    Ava1 = vkuser.Ava1,
                    Uid = vkuser.Uid,
                    Type =  DTO_UserWithCreds.FromString(userClaim.ClaimValue),
                    BanDateTime = userBan
                };
Marco Salerno
  • 5,131
  • 2
  • 12
  • 32
1

Your problem is here:

let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : null

What type is userBan? How is the compiler supposed to figure it out? userBanOffset.Value.Date is a DateTime, but null isn't and can't be a DateTime because DateTime is a value type and value types cannot be null.

So to solve this problem, you need to tell it that null is a Nullable<DateTime> so it can resolve the ambiguity:

let userBan = userBanOffset.HasValue ? userBanOffset.Value.Date : (DateTime?)null

You could also do:

let userBan = userBanOffset.HasValue ? (DateTime?)userBanOffset.Value.Date : null

But personally I always use the former. Depends on which you think is more readable.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • Thank you, I was not able to think of "(DateTime?)null" thing. Also, there is https://stackoverflow.com/questions/44681362/an-expression-tree-lambda-may-not-contain-a-null-propagating-operator so it might not work at all? I am adding much code so cant test this part right now. – Michael Snytko Jul 17 '20 at 06:15
-1

Change

BanDateTime = contextUser.LockoutEnd?.DateTime

to

BanDateTime = (contextUser.LockoutEnd == null) ? null : contextUser.LockoutEnd.DateTime
dsmolen
  • 97
  • 1
  • 5
  • 1
    This has the same issue as the first one because conditional operator doesn't know what type should be used for `DateTime` and `null`. Also the OP has a typo. It should be `contextuser.LockoutEnd.Date`. – juharr Jul 14 '20 at 13:29