如何在N层解决方案中使用LINQ To SQL?

时间:2020-03-05 18:46:00  来源:igfitidea点击:

既然LINQ to SQL更加成熟了,我想知道人们正在使用该技术创建n层解决方案的任何技术,因为在我看来,这似乎并不那么明显。

解决方案

回答

恩,罗克福德·洛特卡(Rockford Lhotka)感到遗憾,因为LINQ to SQL是从数据库中获取数据的出色技术。他建议,之后必须将它们绑定到"到达域对象"(又名CSLA objetcs)。

认真地说,LINQ to SQL具有对n层体系结构的支持,请参见DataContext.Update方法。

回答

我们可能希望研究ADO .Net实体框架,以替代LINQ to SQL,尽管它也支持LINQ。我相信LINQ to SQL的设计是相当轻巧和简单的,而Entity Framework的工作量更大,并且可能更适合大型企业应用程序。

回答

Seriously speaking, LINQ to SQL had it's support for n-tier architecture see DataContext.Update method

我读过的一些书暗示业务逻辑包装了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到底给我买了什么?

我认为我可能以错误的方式看待事物。任何启发将不胜感激。

回答

"唯一可以返回此值的方法是将其作为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的方式相同。

回答

LINQ to SQL并没有真正的n层故事,因为它创建的对象是在类中与其余部分一起创建的,因此实际上并没有一个可以很好地引用的程序集诸如Web服务之类的东西。

我真正认为它的唯一方法是使用datacontext来获取数据,然后填充一个中间数据模型,将其传递并在两端进行引用,然后在客户端使用它,然后将其传递回并推送数据返回到新的Datacontext或者在重新获取行后进行智能更新。

那是因为如果我了解我们要达到的目标:\

当我第一次开始查看ScottGu时,我在他的博客上问了同样的问题,但是我还没有看到一个狂放地使用LINQ to SQL的场景或者应用。 Rob Connery的Storefront等网站离提供商更近。

回答

@liammclennan

Which will return IEnumerable. ... Linq-to-sql is an ORM. It does not affect the way that you design an N-tiered application. You use it the same way you would use any other 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

这就是我的意思,"我失去了良好的打字善良"。我认为我开始同意坩埚; LINQ-to-SQL并非旨在以这种方式使用。再说一次,如果我没有正确看清事物,那么有人可以向我展示方式:)

回答

好的,我将给自己一个可能的解决方案。

插入/更新从来都不是问题。我们可以将业务逻辑包装在"保存/更新"方法中;例如

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

对于获取数据或者至少从多个表中获取数据,可以使用存储过程或者视图,因为结果不是匿名的,因此可以从外部方法返回它们。例如,使用存储的proc:

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

        var emps = context.GetEmployeesAndManagers();

        return emps;
    }