Anular a referência de possivelmente uma referência nula no Entity Framework 6 consulta

0

Pergunta

Eu tenho um .LÍQUIDO 6 projeto com anulável tipos de referência habilitado (<Nullable>enable</Nullable>). Eu tenho esse EF entidade:

public class PostFile {
  public Int32 UserId { get; set; }
  public Int32 PostId { get; set; }

  public virtual User? User { get; set; }
  public virtual Post? Post { get; set; }
}

Eu adicionados ? acima para evitar que este anulável aviso:

Non-nullable property '...' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Agora, eu tenho esse Entity Framework 6 consulta LINQ:

var postFiles = context.postFiles.Where(x => x.User.Id == request.UserId);

... mas eu receber o seguinte aviso:

Dereference of a possibly null reference.

... sobre esta parte da minha consulta:

x.User.Id == ...

Como posso corrigir esse aviso?

4

Melhor resposta

2

Eu acho que você quis dizer algo como:

public class PostFile {
    public Int32 UserId{ get; set; }
    public Int32 PostId { get; set; }

    public virtual User? User { get; set; }
    public virtual Post? Post { get; set; }
}

O problema original é um aviso de que C#8 introduzido com o ser mais explícita com nulo capaz de tipos de referência. Para uma entidade, a implementação acima não é válida, a menos que estas relações são de fato opcional, o que exigiria seus FK campos (id de utilizador e PostId) para também ser Nulo capaz. Eles provavelmente não opcional.

As principais opções para resolver este problema:

A) desligar o recurso. (Desativar nulo capaz de referências no projeto)

B) Pedir "perdão" para o fato de que estes nunca devem ser nulo, mas não vai ser em um estado válido em construção. (EF para gerenciá-las)

public class PostFile {
    public Int32 UserId{ get; set; }
    public Int32 PostId { get; set; }

    public virtual User User { get; set; } = null!;
    public virtual Post Post { get; set; } = null!;
}

Alterar o modelo para marcar as propriedades de navegação como nulo capaz de referências é susceptível de causar todos os tipos de problemas como as migrações ele pode, e vai começar a substituir os não-nulo capaz de FKs com null-capaz queridos. Para marcar estas referências como Nulo e capaz de manter EF feliz:

public class PostFile {
    public Int32? UserId{ get; set; }
    public Int32? PostId { get; set; }

    public virtual User? User { get; set; }
    public virtual Post? Post { get; set; }
}

O que é quase certamente não o que você quer no seu domínio, ou mesmo legal se o id de utilizador e PostId são parte de um PK.

Pessoalmente, eu estou assinando esta alteração em C# como uma "terra de minas" MS habilitado inicialmente por padrão, tais como do Lado do Cliente de Avaliação em EF. :) Eu prevejo muitos-um-StackOverflow perguntas sobre este aviso ou alterações mais recentes, e muitos-um-cliente antigo cheio de "!" perdão marcas mais velhos não-nulo capaz de objetos/referências são transmitidos em código com nulo capaz de verificações de referência.

2021-11-24 23:15:24
1

Você deve marcar navegação entidades como anulável. Você não deve ter carregamento lento habilitado, e, portanto, as propriedades de navegação pode ser retornada como null a partir de consultas. Mesmo se eles são necessários no banco de dados, o seu código não ter que carregá-los.

Em suas expressões de consulta, você pode estar certo de que o Entity Framework não vai executá-las de forma aberta, mas analisar uma consulta SQL para fora deles.

Portanto:

.Where(x => x.User!.Id == request.UserId)

Você pode dizer ao compilador com User! que você sabe que não vai ser nulo lá. A menos que você ative clientside de avaliação, mas você não deve, e se você fizer isso, você vai precisar de um nulo verificação de qualquer jeito.

Como para o uso de PostFile.User, como em:

var postFile = dbContext.PostFiles.FirstOrDefault(p => p....) ?? throw ...;
var user = postFile.User;

Lá ele pode ser null se você não Include(p => p.User) e não tem carregamento lento habilitado, para user precisaria de um nulo verificar antes do uso.

Se você não usar o carregamento lento, você pode desativar o aviso:

#pragma warning disable CS8618 // EF initializes these properties through lazy loading
    public virtual User User { get; set; }
#pragma warning restore CS8618 
2021-11-24 22:37:30
0

Eu acho que você precisa esta:

public class PostFile {
    public User User { get; set; }
    public Post Post { get; set; }
}

E chamada de

var postFiles = context.postFiles.Where(x => x.User.Id == request.UserId).Include(x => x.Post);
2021-11-24 22:52:47

Não. Não a marcação dessas propriedades como anulável faz com que o compilador emitir avisos de que eles podem não ser inicializados, o que é verdade.
CodeCaster
0

O que sobre var postFiles = context.postFiles.Where(x => x.User != null && x.User.Id == request.UserId);?

2021-11-24 22:53:01

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................