Вопрос по linq-to-sql, linq, c# – Как вернуть результаты запроса из метода, который использует LINQ to SQL

1

Вот код, с которым я работаю, я все еще немного новичок в LINQ, так что эта работа еще не завершена. В частности, я хотел бы получить результаты этого запроса (около 7 столбцов строк, целых и даты и времени) и вернуть их методу, который вызвал метод, содержащий этот запрос LINQ to SQL. Простой пример кода был бы очень полезен.

using (ormDataContext context = new ormDataContext(connStr))
{
    var electionInfo = from t1 in context.elections
               join t2 in context.election_status
               on t1.statusID equals t2.statusID
               select new { t1, t2 };
}

(В этом случае мой запрос возвращает все содержимое 2 таблиц выборы и выборы.)

Ваш Ответ

7   ответов
1

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

Но я предлагаю не возвращать результат в новом типе, а вернуть просто наборelection объекты и доступ кelection_status объекты через свойства отношений, предполагая, что вы включили их в свою модель. Параметры загрузки данных заставляют запрос включать связанные объекты статуса выборов в результат запроса.

public IList<election> GetElections()
{
    using (ormDataContext context = new ormDataContext(connStr))
    {
        DataLoadOptions dlo = new DataLoadOptions();
        dlo.LoadWith<election>(e => e.election_status);
        context.DeferredLoadingEnabled = false;
        context.LoadOptions = dlo;   
        return context.elections.ToList();
    }
}

Теперь вы можете сделать следующее.

IList<election> elections = GetElections();

// Access the election status.
Console.WriteLin(elections[0].election_status);

В целом, LINQ to SQL может просто извлекать связанные объекты по запросу - это называется отложенной загрузкой.

ormDataContext context = new ormDataContext(connStr));

IList<election> elections = context.elections.ToList();

// This will trigger a query that loads the election
// status of the first election object.
Console.WriteLine(elections[0].election_status);

Но это требует, чтобы вы не закрывали контекст данных до тех пор, пока вы не закончили использовать извлеченные объекты, поэтому не можете использоваться сusing оператор, заключенный в методе.

Я заметил :) Я также не понял, что вы можете использовать LoadWith в контексте - я видел, что это пригодится. Спасибо!
Хорошие сроки - только что добавили отложенную загрузку через 23 секунды после вашего комментария. ^^
Другой альтернативой является создание контекста без использования. Таким образом, вам не нужно будет вызывать LoadWith несколько раз (в зависимости от сложности вашего запроса). Побочные эффекты этого состоят в том, что контекст не будет автоматически удаляться, а некоторые запросы будут отложены (выборы.избрания_стата).
1

using (ormDataContext context = new ormDataContext(connStr))
{
var electionInfo = from t1 in context.elections
                    join t2 in context.election_status
                    on t1.statusID equals t2.statusID
                    select new { 
                    t1.column1,
                    t1.column2,
                    t1.column3,
                    t1.column4,
                    t2.column5,
                    t2.column6,
                    t2.column7
                    };
}
foreach (var ei in electionInfo){
//write what do u want
}
это говорит о 7, что, если их было меньше или больше?
Вы можете выбрать что угодно в select new {...}, просто выделите имя столбца и таблицу :)
0

объеме, в котором он создан. Вместо этого вам придется создать класс.

@NagaMensch ... это не так уж важно. Вам просто нужен класс с теми свойствами, которые вы возвращаете анонимному типу ... автоматические свойства делают его довольно быстрым.
Это кажется очень утомительным способом справиться с каждым вызовом БД ... alchemical
Вы можете вернуть его, но типом времени компиляции будет объект.
@Eulerfx, да, это то, что я имею в виду, информация о типе пропала. Если вы не используете отражение.
Вы действительно думаете, что создание объекта для каждого отдельного вызова БД - это просто? Большой проект может легко иметь сотни вызовов БД ... затем, когда БД меняется, код становится хрупким и требует масштабных утомительных изменений. alchemical
0
return electionInfo.ToList();
а список какого типа? alchemical
Как бы вы определили список в вызывающем методе? Я попытался и столкнулся с проблемами с List, нуждающимся в типе, но у нас есть только анонимный тип (?) alchemical
Это должен быть список или что-то в этом роде, поскольку контекст данных неуклонно удаляется, поэтому возвращение IQueryable или IEnumerable и последующая оценка запроса приведут к исключению из-за доступа к удаленному объекту.
Элементы, выбранные запросом, имеют анонимный тип. Какой тип возврата вы предлагаете при использовании этого оператора возврата? Кроме того, OP, по-видимому, не требует, чтобы данные сохранялись в списке. Преобразование в список AFAIK означает активное чтение всех элементов, даже если клиент этого не делает. Почему список?
5

results from this query (about 7 columns of strings, ints, and datetime), and return them

Здравствуйте, проблема, с которой вы столкнулись при запросе, заключается в том, что вы создаете анонимный тип. Вы не можете вернуть анонимный тип из метода, поэтому у вас возникнут проблемы.

Что вам нужно сделать, это создать «обертку» тип, который может принимать выборы и выбор_стата, а затем возвращать их.

Вот небольшой пример того, о чем я говорю; как вы можете видеть, я объявляю класс Tuple. Метод, в который вы поместите запрос, возвращает IEnumerable.

Надеюсь, это поможет :-)

class Tuple
{
    Election election;
    Election_status election_status;

    public Tuple(Election election, Election_status election_status)
    {
        this.election = election;
        this.election_status = election_status;
    }
}

public IEnumerable<Tuple> getElections()
{
    IEnumerable<Tuple> result = null;

    using (ormDataContext context = new ormDataContext(connStr))
    {
        result = from t1 in context.elections
                 join t2 in context.election_status
                 on t1.statusID equals t2.statusID
                 select new Tuple(t1, t2);
    }
}

UPDATE

Следуя комментариям NagaMensch, лучшим способом достижения желаемого результата было бы использование встроенных связей LINQ to SQL.

Если вы перейдете к диаграмме вашей сущности и нажмете на панель инструментов, вы увидите 3 варианта. Класс, Ассоциация и Наследование. Мы хотим использоватьAssociation.

Click on Association and click on the ElectionStatus entity, hold the mouse button down and it will allow you to draw a line to the Election entity.

Once you've drawn the line it will ask you which properties are involved in the association. You want to select the StatusId column from the Election entity, and the StatusId column from the ElectionStatus entity.

Теперь, когда вы завершили сопоставление, вы сможете значительно упростить свой запрос, поскольку объединение не потребуется. Вы можете просто получить доступ к состоянию выборов через совершенно новое свойство, которое LINQ to SQL добавит в объект Election.

Ваш код теперь может выглядеть так:

//context has to be moved outside the function
static ExampleDataContext context = new ExampleDataContext();

//Here we can return an IEnumerable of Election now, instead of using the Tuple class
public static IEnumerable<Election> getElections()
{
    return from election in context.Elections
           select election;
}

static void Main(string[] args)
{
    //get the elections
    var elections = getElections();

    //lets go through the elections
    foreach (var election in elections)
    {
        //here we can access election status via the ElectionStatus property
        Console.WriteLine("Election name: {0}; Election status: {1}", election.ElectionName, election.ElectionStatus.StatusDescription);
    }
}

Вы также можете найти & quot; как & quot; на LINQ to SQL ассоциацииВот.

Примечание. Стоит упомянуть, что если между вашими таблицами в базе данных установлены отношения FK; LINQ to SQL автоматически выберет связь и отобразит связь для вас (создавая свойства).

Новичок в LINQ и использовал этот же метод несколько раз.
Я обновил ответ, чтобы объяснить, как использовать ассоциации для реализации гораздо лучшего решения. Если вы застряли вообще или вам нужны дальнейшие объяснения, просто дайте мне знать :-) Надеюсь, это поможет.
Я попробую, спасибо. Мое единственное беспокойство заключается в том, что это похоже на подход db table-center, тогда как мне нравится архитектура, которая дает мне свободу запрашивать любые результаты, которые мне нужны, то есть они могут даже не приходить из таблицы и т. Д. Итак, я думаю, в этом случае я бы застрял, создавая десятки или даже сотни этих пользовательских объектов только для хранения наборов результатов данных ... alchemical
Действительно, вы правы. Было бы ужасной идеей реализовывать классы в этом стиле каждый раз, когда вы хотите вернуть результаты запроса. В LINQ to SQL вы можете сообщить разработчику, что между этими двумя объектами существует связь, и это позволит вам получить доступ к связанному объекту через свойство. Таким образом, вы можете вернуть Election, а затем получить доступ к статусу, вызвавlection.election_status. Это было бы намного лучшим способом сделать это и также поддержало бы целостность вашего объединения.
это сохранит целостность соединения SQL? alchemical
1
IEnumerable<object> getRecordsList()
    {
        using (var dbObj = new OrderEntryDbEntities())
        {
            return (from orderRec in dbObj.structSTIOrderUpdateTbls
                    select orderRec).ToList<object>();
        }
    }
Это проверено Метод C # 4.0
1

имеющие ту же структуру, что и анонимные типы. Затем вместо «new {t1, t2}» вы используете «new MyClass (t1, t2)».

Если у вас есть именованный класс, вы можете передать его повсюду, как и надеялись.

Похожие вопросы