Как использовать LINQ To SQL в N-уровневом решении?

StackOverflow https://stackoverflow.com/questions/38005

  •  09-06-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

Это если я понимаю, что вы пытаетесь понять: \

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

Другие советы

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

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

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

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

Вставки / обновления никогда не были проблемой; вы можете обернуть бизнес-логику в метод 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;
    }
  

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

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

То, как я традиционно пишу бизнес-объекты, обычно инкапсулирует «методы загрузки». в БО тоже; поэтому у меня может быть метод с именем 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, если мне нужно все это делать?

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

" единственный способ вернуть это как 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.

@лиам кленнан

Который вернет 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 не был разработан для использования таким образом.Опять же, если я не вижу все правильно, кто-нибудь, покажите мне путь :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top