C# Linq Guid Проблема анонимного типа

У меня есть запрос linq, который возвращает идентификатор вопроса на основе текста вопросов. Затем этот идентификатор необходимо использовать, чтобы связать дату в таблице дат с этим конкретным вопросом. Вопрос уже сохранен, а дата сохранена в другое время.

Проблема в том, что запрос возвращает идентификатор вопроса как анонимный тип, поэтому, когда мне нужно назначить этот идентификатор вопроса в качестве идентификатора вопроса в другой таблице, он выдает ошибку, утверждая, что таблица ожидает Guid. После этого я преобразовал анонимный тип в строку, а затем использовал функцию преобразования GUID для преобразования строки в GUID, однако теперь мне выдается ошибка, что GUID должен состоять из 32 символов и 4 тире.

Мои мысли по этому поводу заключаются в том, что анонимный тип возвращает questionID как «QuestionID = jkj939-89239829-etc и т. д.». - С префиксом символов впереди и, таким образом, при преобразовании в GUID преобразованная строка содержит эти символы.

Я что-то пропустил? Я действительно не могу понять, зачем это делать, и есть ли способ удалить префикс, возвращаемый анонимным типом? Помощь будет принята с благодарностью.

Вот код:

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;
        }
    }

person Goober    schedule 05.05.2009    source источник


Ответы (5)


Если я что-то не упустил, почему бы вам просто select q.QuestionID вместо создания новой оболочки анонимного типа?

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());
}

В качестве альтернативы можно присвоить полю имя ("theID" ниже) и получить к нему прямой доступ:

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());
}

Судя по всему, вопрос был шире, чем я думал сначала. В ответ на комментарий имейте в виду, что вы возвращаете перечисление результатов в matchedques (отсюда и foreach выше, верно?). Таким образом, следующая строка также ошибочна:

string qidGuidString = matchedques.ToString();

Вы либо хотите

string qidGuidString = matchedques.Single().ToString();

если matchedques должен содержать один результат, или цикл foreach, если matchedques должен содержать несколько результатов.


Обратите внимание, что нет необходимости преобразовывать GUID в строку и обратно, и вы также можете использовать запрос, чтобы вернуть что-то более полезное (а именно, новый объект 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();
}
person lc.    schedule 05.05.2009
comment
Я попробовал это, изменив код на: dlu.QuestionID = matchedques; Получено это: Ошибка: невозможно неявно преобразовать тип «System.Linq.IQueryable‹System.Guid›» в «System.Guid» C:\Documents и - person Goober; 05.05.2009
comment
Здравствуйте, я реализовал пример кода, который вы разместили выше, и теперь, хотя код срабатывает без ошибок, как и раньше, он фактически не вставляет никаких новых деталей. - person Goober; 05.05.2009
comment
Попробуйте поставить точку останова в цикле foreach. Разверните результаты matchedques и посмотрите, получаете ли вы желаемые результаты. На данный момент я не уверен, что ошибка в приведенном выше коде, результаты dc.GetTable‹Question›() или что-то происходит в dlused.Context.SubmitChanges()... - person lc.; 05.05.2009

Почему бы просто не использовать select q.QuestionID; вместо `выберите новый {q.QuestionID};' вещи?

person Anton Gogolev    schedule 05.05.2009
comment
Я попробовал это, изменив код на: dlu.QuestionID = matchedques; Получено это: Ошибка: невозможно неявно преобразовать тип «System.Linq.IQueryable‹System.Guid›» в «System.Guid» C:\Documents и - person Goober; 05.05.2009
comment
sahgilbert - см. мой ответ ниже - person Winston Smith; 05.05.2009

Вы вызываете .ToString() для matchedques, который является перечислением:

var matchedques = from q in dc.GetTable<Question>()
                            where q.QuestionText.Contains(quesText)
                            select new{
                                q.QuestionID
                            };

string qidGuidString = matchedques.ToString();

Итак, в приведенном выше примере matchedques представляет собой перечисление анонимных типов (вероятно, вам следует покончить с этим и напрямую выбрать q.QuestionID). Вызов ToString() для этого вернет строковое представление объекта, а не просто QuestionId первого элемента последовательности.

Вы ожидаете, что для вышеуказанного запроса всегда будет только один результат? Если это так, вам, вероятно, следует взглянуть на оператора Single.

Что-то вроде этого должно делать:

var matchedQuesId = 
    dc.GetTable<Question>()
    .Where(q =>q.QuestionText.Contains(quesText))
    .Single()
    .QuestionID;

В этом случае вы можете напрямую использовать matchedQuesId. Обратите внимание, что если запрос Where не соответствует ни одному элементу или более чем одному элементу, это приведет к ошибке. Прочтите статью об одном операторе, чтобы узнать, почему.

person Winston Smith    schedule 05.05.2009

Попробуй это:

var matchedques = (from q in dc.GetTable<Question>()
                  where q.QuestionText.Contains(quesText)
                  select new{
                      q.QuestionID
                  }).FirstOrDefault();

Тогда просто:

if (matchedques != null){
    // Just use matchedques.QuestionID to get your value
}

FirstOrDefault установит matchedques var для одного экземпляра объекта, а не для их перечисления. Работает удовольствие, когда вы знаете, что вам нужно только одно значение. Бит OrDefault означает, что будет NULL, если ничего не найдено.

person user535927    schedule 29.02.2012

Изменить на:

...
var matchedques = from q in dc.GetTable<Question>()
                        where q.QuestionText.Contains(quesText)
                        select q.QuestionID;

например удалить новый {...}, поэтому вы создаете новый тип анонимной мыши со свойством id.

person Kamarey    schedule 05.05.2009
comment
Если вы проголосовали против, пожалуйста, укажите причину. Какая проблема с этим ответом? - person Kamarey; 05.05.2009