Как использовать LINQ To SQL в N-уровневом решении? - PullRequest
15 голосов
/ 01 сентября 2008

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

Ответы [ 7 ]

1 голос
/ 02 сентября 2008

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

Единственный способ, которым я действительно рассмотрел бы его, - это использование datacontext для выборки данных, затем заполнение промежуточной модели данных, прохождение через нее, обращение к ней с обеих сторон и использование ее на стороне клиента - затем передача их обратно и отправка данных обратно в новый Datacontext или интеллигентное обновление строк после их повторного получения.

Вот если я понимаю, к чему вы стремитесь: \

Я задал ScottGu тот же вопрос в его блоге, когда впервые начал смотреть на него, но я не видел ни одного сценария или приложения, которые бы использовали LINQ to SQL таким образом. Такие сайты, как магазин Роба Коннери, ближе к поставщику.

1 голос
/ 02 сентября 2008

ОК, я собираюсь дать себе одно возможное решение.

Вставки / обновления никогда не были проблемой; вы можете обернуть бизнес-логику в метод Save / Update; например,

public class EmployeesDAL
{
    ...
    SaveEmployee(Employee employee)
    {
        //data formatting
        employee.FirstName = employee.FirstName.Trim();
        employee.LastName = employee.LastName.Trim();

        //business rules
        if(employee.FirstName.Length > 0 && employee.LastName.Length > 0)
        {
            MyCompanyContext context = new MyCompanyContext();

            //insert
            if(employee.empid == 0)
             context.Employees.InsertOnSubmit(employee);
            else
            {
              //update goes here
            }

            context.SubmitChanges();


        }
        else 
          throw new BusinessRuleException("Employees must have first and last names");
     }
 }

Для выборки данных или, по крайней мере, для выборки данных, поступающих из более чем одной таблицы, вы можете использовать хранимые процедуры или представления, поскольку результаты не будут анонимными, поэтому вы можете вернуть их из внешнего метода. Например, используя сохраненный процесс:

    public ISingleResult<GetEmployeesAndManagersResult> LoadEmployeesAndManagers()
    {
        MyCompanyContext context = new MyCompanyContext();

        var emps = context.GetEmployeesAndManagers();

        return emps;
    }
1 голос
/ 01 сентября 2008

Возможно, вы захотите взглянуть на ADO .Net Entity Framework в качестве альтернативы LINQ to SQL, хотя она также поддерживает LINQ. Я считаю, что LINQ to SQL спроектирован так, чтобы быть достаточно легким и простым, тогда как платформа Entity Framework более тяжелая и, вероятно, больше подходит для крупных корпоративных приложений.

1 голос
/ 01 сентября 2008

Хм, Rockford Lhotka печально, что LINQ to SQL - замечательная технология для извлечения данных из базы данных. Он предполагает, что после этого они должны будут быть привязаны к «объектам домена» (aka. CSLA objetcs).

Если серьезно, LINQ to SQL имел поддержку n-уровневой архитектуры, см. DataContext.Update метод.

0 голосов
/ 02 сентября 2008

@ liammclennan

Который вернет IEnumerable. ... Linq-to-sql - это ORM. Это не влияет на способ разработки N-уровневого приложения. Вы используете его так же, как и любой другой ORM.

Тогда, я думаю, я все еще в замешательстве. Да, Linq-to-Sql - это ORM; но, насколько я могу судить, я все еще засоряю свой код переднего плана встроенными операторами типа sql (linq, а не sql ...., но все же я чувствую, что это следует абстрагировать от внешнего интерфейса).

Предположим, я обернул оператор LINQ, который мы использовали в качестве примера в методе. Насколько я могу судить, единственный способ вернуть это так:

public class EmployeesDAL
{
    public IEnumerable LoadEmployeesAndManagers()
    {
            MyCompanyContext context = new MyCompanyContext();

            var emps = from e in context.Employees
            join m in context.Employees
            on e.ManagerEmpID equals m.EmpID
            select new
                      { e,
                        m.FullName
                      };

            return emps;
    }

}

Из моего внешнего кода я бы сделал что-то вроде этого:

EmployeesDAL dal = new EmployeesDAL;
var emps = dal.LoadEmployeesAndManagers();

Это, конечно, возвращает IEnumerable; но я не могу использовать это как любой другой ORM, как вы говорите (если, конечно, я неправильно понимаю), потому что я не могу сделать это (опять же, это надуманный пример):

txtEmployeeName.Text = emps[0].FullName

Это то, что я имел в виду под "я теряю сильное типизированное совершенство". Я думаю, что я начинаю соглашаться с Crucible; что LINQ-to-SQL не был разработан для такого использования. Опять же, если я не вижу вещи правильно, кто-то покажет мне путь:)

0 голосов
/ 02 сентября 2008

«Единственный способ вернуть это - это IEnumerable, так что я теряю свою сильную печатность»

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

var emps = from e in Employees
            join m in Employees
            on e.ManagerEmpID equals m.EmpID
            select new Employee
                      { e,
                        m.FullName
                      };

Который вернет IEnumerable.

Вот статья Я написал по теме.

Linq-to-sql - это ORM. Это не влияет на способ разработки N-уровневого приложения. Вы используете его так же, как и любой другой ORM.

0 голосов
/ 01 сентября 2008

Серьезно говоря, LINQ to SQL имел поддержку n-уровневой архитектуры, см. Метод DataContext.Update

Часть того, что я прочитал, предполагает, что бизнес-логика оборачивает DataContext - другими словами, вы оборачиваете обновление так, как вы предлагаете.

То, как я традиционно пишу бизнес-объекты, я обычно также инкапсулирую в "методы загрузки" в BO; поэтому у меня может быть метод с именем LoadEmployeesAndManagers, который возвращает список сотрудников и их непосредственных руководителей (это надуманный пример). Может быть, это только я, но в моем интерфейсе я предпочел бы увидеть e.LoadEmployeesAndManagers (), чем какой-то длинный оператор LINQ.

В любом случае, используя LINQ, он, вероятно, будет выглядеть примерно так (не проверяется на правильность синтаксиса):

var emps = from e in Employees
                join m in Employees
                on e.ManagerEmpID equals m.EmpID
                select new
                          { e,
                            m.FullName
                          };

Теперь, если я правильно понимаю вещи, если я помещу это, скажем, в библиотеку классов и вызову ее из моего интерфейса, единственный способ, которым я могу вернуть это, - это IEnumerable, так что я теряю свое строгое типизированное совершенство. Единственный способ вернуть строго типизированный объект - это создать собственный класс Employees (плюс строковое поле для имени менеджера) и заполнить его по результатам моего оператора LINQ to SQL, а затем вернуть его. Но это кажется нелогичным ... что именно купил мне LINQ to SQL, если я должен все это делать?

Я думаю, что я могу смотреть на вещи неправильно; любое просвещение будет оценено.

...