LINQ to SQL estranho Issue Junte
-
08-07-2019 - |
Pergunta
Eu tenho um banco de dados simples com duas mesas. Usuários e configurações. Um usuário tem uma chave estrangeira para vinculá-lo a uma configuração particular.
Estou tendo um problema estranho onde a seguinte consulta sempre causa uma junção interna para a tabela de configuração, independentemente do valor do segundo parâmetro. Tanto quanto eu posso dizer, mesmo que o "UserConfiguration =" parte do objeto de inicialização é condicional, LINQ não vê que e determina que um relacionamento é seguido em qualquer caso.
Se eu realmente remover a última inicialização, a coisa toda funciona como esperado. Não junção interna quando loadConfiguration == false e se junta ao loadConfiguration == true.
Alguém tem alguma idéia sobre isso? É esta sintaxe simplesmente não vai funcionar? O único pensamento que tenho agora é para embrulhar o retorno em um básico if -. Eu só queria evitar as linhas duplicadas
public UserAccount GetByUsername(string username, bool loadConfiguration)
{
using (Database database = new Database())
{
if (loadConfiguration)
{
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<User>(c => c.Configuration);
database.LoadOptions = loadOptions;
}
return (from c in database.Users
where c.Username == username
select new UserAccount
{
ID = c.ID,
ConfigurationID = c.ConfigurationID,
Username = c.Username,
Password = c.Password.ToArray(),
HashSalt = c.HashSalt,
FirstName = c.FirstName,
LastName = c.LastName,
EmailAddress = c.EmailAddress,
UserConfiguration = (loadConfiguration) ? new ApplicationConfiguration
{
ID = c.Configuration.ID,
MonthlyAccountPrice = c.Configuration.MonthlyAccountPrice,
TrialAccountDays = c.Configuration.TrialAccountDays,
VAT = c.Configuration.VAT,
DateCreated = c.Configuration.DateCreated
} : null
}).Single();
}
}
Agradecemos antecipadamente,
Martin.
Solução
Eu não acho que ele vai trabalhar assim.
Eu sugiro dividindo-o em 2 consultas distintas.
Existem provavelmente melhores maneiras, mas isso exigiria mais 'plumbling'.
Outras dicas
Não, isso não vai funcionar. Já corri em problemas semelhantes muitas vezes. A razão para isso tem a ver com expressões em condições de tempo versus compilação em tempo de execução.
Você pode fazer 2 perguntas ou se você não se importa se juntar à configuração independentemente do parâmetro loadConfiguration, você poderia usar:
var q = (from c in database.Users
where c.Username == username
select c).Single();
e, em seguida, usar Linq-to-Objects no resultado.
Substituir .Single () com SingleOrDefault () e Linq irá mudar para uma junção externa esquerda. Eu não sei se no seu caso ele vai fazê-lo, mas em alguns casos ele faz.
Editar DINT ver o single foi para toda a consulta e não para a parte de configuração:
tente o seguinte:
UserConfiguration = (loadConfiguration && c.Configuration != null) ? new ApplicationConfiguration
{
ID = c.Configuration.ID,
MonthlyAccountPrice = c.Configuration.MonthlyAccountPrice,
TrialAccountDays = c.Configuration.TrialAccountDays,
VAT = c.Configuration.VAT,
DateCreated = c.Configuration.DateCreated
} : null