C # Linq Guid Anonymous Tipo de Problemas
-
05-07-2019 - |
Pergunta
Eu tenho uma consulta linq que retorna o ID de uma pergunta com base no texto perguntas. é então necessário este ID a ser usado para relacionar uma data em uma tabela de data para essa pergunta particular. A questão já está armazenado ea data é armazenada em um horário diferente.
O problema é que a consulta retorna o QuestionID como um tipo anônimo e assim quando eu preciso atribuir esse QuestionID como o QuestionID em outra tabela, ele lança um erro, informando que a tabela está esperando um Guid. Depois disso, eu converti o tipo anônimo para uma string e, em seguida, usou os GUIDs converter recurso para converter a string para um GUID, no entanto, é agora me dando o erro que um GUID deve ser 32 caracteres e 4 traços.
Os meus pensamentos sobre este são de que o tipo anônimo está retornando o QuestionID como "QuestionID = jkj939-89239829- etc etc." -. Com o prefixo de caracteres na frente, e, portanto, ao converter-lo para um GUID, a cadeia convertida contenha estes caracteres
eu perdi alguma coisa? Eu realmente não posso entender por que ele faria isso, e se existe uma maneira de remover o prefixo retornado pelo tipo anônimo? Ajuda seria muito apreciada.
Aqui está o código:
public static void GetQuesID(string quesText)
{
ExamineDataContext dc = new ExamineDataContext();
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select new{
q.QuestionID
};
foreach (var element in matchedques)
{
MessageBox.Show(element.ToString());
}
try
{
Guid g = Guid.NewGuid();
Table<DateLastUsed> dlused = Repository.GetDateLastUsedTable();
DateLastUsed dlu = new DateLastUsed(); ;
string qidGuidString = matchedques.ToString();
Guid convQuesGuid = new Guid(qidGuidString);
dlu.DLUID = g;
dlu.QuestionID = convQuesGuid;
dlu.DateLastUsed1 = DateTime.Now;
dlused.InsertOnSubmit(dlu);
dlused.Context.SubmitChanges();
}
catch (Exception ex)
{
throw ex;
}
}
Solução
A menos que eu estou faltando alguma coisa, por que você não apenas select q.QuestionID
em vez de fazer um novo tipo anônimo invólucro?
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select q.QuestionID;
foreach (var element in matchedques)
{
MessageBox.Show(element.ToString());
}
Como alternativa, dar o campo um nome ( "theID
" abaixo) e acessá-lo diretamente:
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select new{
theID = q.QuestionID
};
foreach (var element in matchedques)
{
MessageBox.Show(element.theID.ToString());
}
Aparentemente, havia mais para a questão do que eu pensava. Em resposta ao comentário, tenha em mente que você está retornando um enumeração dos resultados em matchedques (daí o foreach acima, certo?). Então a seguinte linha também está em erro:
string qidGuidString = matchedques.ToString();
Você quer quer
string qidGuidString = matchedques.Single().ToString();
Se matchedques deve conter um único resultado, ou um loop foreach se matchedques deve conter vários resultados.
Note que não há nenhuma razão para converter um GUID para string e vice-versa, e você também pode usar a consulta para retornar algo mais útil (ou seja, um novo objeto DateLastUsed
):
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select new DateLastUsed() {
DLUID = Guid.NewGuid(),
QuestionID = q.QuestionID,
DateLastUsed1 = DateTime.Now
};
Table<DateLastUsed> dlused = Repository.GetDateLastUsedTable();
foreach(var dlu in matchedques)
{
dlused.InsertOnSubmit(dlu);
dlused.Context.SubmitChanges();
}
Outras dicas
Por que não apenas select q.QuestionID;
em vez deste `selecionar nova {q.QuestionID};' material?
Você está chamando .ToString () no matchedques, que é uma enumeração:
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select new{
q.QuestionID
};
string qidGuidString = matchedques.ToString();
Assim, no seu exemplo acima, matchedques é um enunmeration de tipos anônimos (você provavelmente deve acabar com isso e seleccionar q.QuestionID diretamente). Chamando ToString () nesse irá retornar uma representação de string do objeto, e não simplesmente o QuestionID do primeiro elemento da seqüência.
Você está esperando que haja sempre um só resultado para a consulta acima? Se assim for, você provavelmente deve olhar para o operador único.
Algo como isso deve fazer:
var matchedQuesId =
dc.GetTable<Question>()
.Where(q =>q.QuestionText.Contains(quesText))
.Single()
.QuestionID;
Neste caso, você pode usar matchedQuesId diretamente. Note-se que se o Onde consulta corresponde a nenhum, ou mais de um elementos, isto irá lançar um erro. Leia-se sobre o operador único para descobrir o porquê.
Tente isto:
var matchedques = (from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select new{
q.QuestionID
}).FirstOrDefault();
Em seguida, basta:
if (matchedques != null){
// Just use matchedques.QuestionID to get your value
}
FirstOrDefault
irá definir o matchedques
var a uma única instância do objeto, não um ennumeration deles. Funciona um deleite quando você sabe que não é apenas um valor desejado. Os meios OrDefault
bit será NULL
se nada encontrou.
Change to:
...
var matchedques = from q in dc.GetTable<Question>()
where q.QuestionText.Contains(quesText)
select q.QuestionID;
por exemplo. remover novo {...}, então você está criando um novo tipo anonimouse com a propriedade id.