如何在N层解决方案中使用LINQ To SQL?
既然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; }