我目前有一个应用程序,其中包括: 用户界面(网页) BLL(经理和域对象) DAL(我的每个域对象的DataAccess类)。
我在UI中使用以下内容来搜索域对象。
protect sub Button1_Click()
{
IBook book = BookManager.GetBook(txtID.Text);
}
这是我的BLL
public class BookManager
{
public static IBook GetBook(string bookId)
{
return BookDB.GetBook(bookId);
}
}
public class Book : IBook
{
private int? _id
private string _name;
private string _genre;
public string Name
{
get { return _name; }
private set
{
if (string.IsNullOrEmpty(value))
throw new Exception("Invalid Name");
_name = value;
}
}
public string Genre
{
get { return _serial; }
private set
{
if (string.IsNullOrEmpty(value))
throw new Exception("Invalid Genre");
_genre = value;
}
}
// Other IBook Implementations
}
最后这是我的DAL
public class BookDB
{
public static IBook GetBook(int id)
{
// Get Book from database using sproc (not allowed to use any ORM)
// ?? Create IBook Item?
// return IBook
}
如何创建IBook对象并将其返回给Manager? 我正在考虑将一个DataTable从BookDB返回到BookManager并让它创建Book对象并将其返回,但这似乎不对。 还有另一种方法吗?
修改: 我决定将每个图层分成一个项目,并在尝试添加对BLL的引用时在DAL层中遇到循环依赖问题。 我无法从DAL访问Book Class或Interface或BLL中的任何内容。 我应该在这里使用ado.net对象并让我的经理从ado.net对象创建实际对象吗? 以下是它的布局方式
BLL.Managers - BookManager
BLL.Interfaces IBook
BLL.Domain - Book
DAL - BookDB.
谢谢!
答案 0 :(得分:5)
您可以创建仅包含数据的虚拟Book对象。获取,设置属性和成员值。本书对数据库中的每个字段都有1个属性,但不验证任何内容。
从db填充对象,然后将其发送到BLL。
如果要保存对象,还可以将其发送到BLL。
如果有意义的话,BLL中的类可以包裹那些对象。这样,很容易将其发送回DAL。
虚拟书:
public class DummyBook:IBook
{
private nullable<int> _id;
private string _name;
private string _genre;
public string Id
{
get {return _id;}
set {_id = value;}
}
public string Name
{
get {return _name;}
set {_name = value;}
}
public string Genre
{
get {return _genre;}
set {_genre= value;}
}
}
DAL书:
public class DALBook
{
public static IBook:GetBook(int id)
{
DataTable dt;
DummyBook db = new DummyBook();
// Code to get datatable from database
// ...
//
db.Id = (int)dt.Rows[0]["id"];
db.Name = (string)dt.Rows[0]["name"];
db.Genre = (string)dt.Rows[0]["genre"];
return db;
}
public static void SaveBook(IBook book)
{
// Code to save the book in the database
// you can use the properties from the dummy book
// to send parameters to your stored proc.
}
}
BLL Book:
public class Book : IBook
{
private DummyBook _book;
public Book(int id)
{
_book = DALBook.GetBook(id);
}
public string Name
{
get {return _book.Name;}
set
{
if (string.IsNullOrEmpty(value))
{
throw new Exception("Invalid Name");
}
_book.Name = value;
}
}
// Code for other Properties ...
public void Save()
{
// Add validation if required
DALBook.Save(_book);
}
}
Edit1:虚拟类应该放在他们自己的项目中(模型,正如评论中所述)。参考文献将如下工作:
DAL引用模型项目。
BLL引用模型和DAL
UI引用BLL。
答案 1 :(得分:2)
BookDB应该返回IBook实例。我喜欢存储库模式,它是关于从db到域的映射。
存储库实现返回域对象的实例。这可以保护代码的其余部分免受特定持久性实现的影响,这可能受到技术(数据库类型,Web服务,[插入其他内容])和用于保存数据的格式的影响。
答案 2 :(得分:1)
我可能会使用ExecuteReader在数据库的代码中创建一个对象。这样做的原因是数据表比读取器具有更多的开销,因为它具有更多功能(并且可能由读者创建)。由于您没有使用数据表进行更新/删除,因此不需要开销。
话虽这么说,我会在BookManager类中创建一个静态辅助方法。
internal static IBook BookFromReader(IDataReader reader)
{
Book B = new Book();
B.Prop = reader.GetString(0);
B.Rinse = reader.Repeat();
return B;
}
之所以这样,是因为您拥有接口的原因是您可能想要更改实现。你最终可能会有INovel:IBook,IReference:IBook等,然后你会想要在你的数据层中有一个抽象的工厂实现。
public static IBook GetBook(int id)
{
// SqlCommand Command = new Command("SQL or sproc", ValidConnection);
using(IDataReader DR = Command.ExecuteReader(id))
{
// checking omitted
switch(DR.GetInt32(1))
{
case 0:
return BookManager.BookFromReader(DR);
case 1:
return BookManager.NovelFromReader(DR);
etc
}
}
}
这里DAL的另一个好处是你可以缓存查找。您可以拥有一个包含您查找过的书籍的词典,以减少对已经返回的对象的额外数据库调用。当发生更新时,你删除了缓存的实体......这是另一篇文章。
如果您正在使用多个程序集,则接口和辅助方法将需要驻留在中性(非依赖)程序集中。现在在博客o-sphere中,有朝着更少的集合的方向发展,这意味着更少的依赖性等等。
以下是我在此主题上阅读的博客链接: http://codebetter.com/blogs/patricksmacchia/archive/2008/12/08/advices-on-partitioning-code-through-net-assemblies.aspx
最终,我认为答案是数据层将您的接口实例返回给业务层。
祝你好运: - )答案 3 :(得分:1)
在我看来,你永远不应该让DAL访问BLL。这是一种不必要的依赖。
将Book类放入一个新项目(可能名为DomainModel)将修复循环引用。你可以这样做:
项目BLL参考DAL和DomainModel
Project DAL参考DomainModel
项目UI参考BLL和DomainModel
Project DomainModel什么都没引用
答案 4 :(得分:0)
您想要返回的DataTable与数据库相关,而对于BLL,它不应该关心您使用的是什么数据库以及架构是什么。 您可以使用DB-Object Mapper将dbtable映射到DAL中的对象。
答案 5 :(得分:0)
如果您不想返回DataTable,可以从BookManager传入IBook实现以填充DAL。
答案 6 :(得分:0)
遵循预期的模型。数据访问层(DAL)负责从数据源检索数据和向数据源发送数据。
DAL必须不关心BLL正在使用的任何业务实体,因为它唯一的工作是检索数据并将其返回到中性对象中。对于通用的可用性,它必须是中性的,否则你也可能不会因为你的目的而将它们分开。
您的业务逻辑层(BLL)必须不关心DAL如何实现检索或写入数据。
要在BLL和DAL之间进行通信,您必须使用中性对象。
您的BLL将对象的属性作为单独的参数传递给DAL中的方法。 DAL中的参数是中性的,使用字符串,int,bool,任何其他.NET对象,这些对象既不特定于您正在与之通信的数据库版本,也不是仅存在于BLL中的特定类型。
DAL将从任何地方检索数据,并将中性数据对象返回给调用者。例如,这可能是DataSet或DataTable或任何其他不特定于您正在使用的数据库类型/版本的对象。因此,DataSet和DataTable是System.Data命名空间中的对象,而不是System.Data.SQL等...命名空间。
实质上: - BLL将中性类型传递给DAL(例如:string,int,bool,long,float等)。 - 如果需要,DAL负责将这些类型转换为数据库特定类型,然后再将它们传递给数据源 DAL将中性数据类型返回给BLL(例如:DataSet,DataTable等)。 - BLL负责使用这些中性数据类型的内容来创建,填充和返回特定业务实体
您的BLL必须参考您的DAL。就是这样。
你可以完全忽略这个模型并破解许多以前使用IBOOK等建议...但是你没有使用预期的模型,并且可能将它全部扔进一个程序集中,因为你不会无论如何能够独立地保持它。