我正在设计一个主要由数据库驱动的个人项目。我正在尝试为如何处理数据库互操作提出一个好的设计,我想在StackOverflow上有经验的思想输入。
以下是好的设计,还是有更标准的方式来处理与数据库的通信?
修改
我主要是在寻找关于是否通常将连接细节分解为自己的基类的反馈,以及逻辑单元/类的子类。
为此,我修改了下面的代码,添加了一个检索方法,以补充原始问题中的插入方法。我还修改了它以显示它需要/返回(取决于方法)业务对象
例如,在示例中,我们在整个应用程序中使用Employee类,但是有一个EmployeeDb类(继承自Database),它处理与数据库之间的持久性。
我喜欢这个,因为它将存储实现细节保留在业务对象之外,但不喜欢它,因为它强烈地耦合了Employee和EmployeeDB类。
// Abstract Base Class to handle specifics of the database connection
abstract class Database : IDisposable
{
protected OleDbConnection m_Conn;
public bool Open()
{
// Open a connection to the database
}
public void Dispose()
{
if (m_Conn != null)
{
m_Conn.Dispose();
}
}
}
// Specific classes for each table, with methods for CRUD functions
class EmployeeDB : Database
{
public bool AddTestData(Employee emp)
{
// Construct SQL to add Employee class members to the DB, breaking
// them out into their component tables as needed
}
public List<Employee> GetEmployeeByProject(string project)
{
// Retrieve recordset of all employees on the project,
// breaking them out into instances of the Employee class
// Add each new Employee object to a list, and return the list
// to the caller.
}
}
// Specific classes for each table (or logical unit, since obviously
// most of the time we'll need to join a few tables to get what
// we want), with methods for CRUD functions
void AddSomethingToTheDatabase()
{
using (TestDataDB td = new TestDataDB())
{
td.Open(Application.StartupPath);
string NewID = td.AddTestData(txtAddMe.Text);
}
}
// Abstract Base Class to handle specifics of the database connection
abstract class Database : IDisposable
{
protected OleDbConnection m_Conn;
public bool Open()
{
// Open a connection to the database
}
public void Dispose()
{
if (m_Conn != null)
{
m_Conn.Dispose();
}
}
}
// Specific classes for each table, with methods for CRUD functions
class EmployeeDB : Database
{
public bool AddTestData(Employee emp)
{
// Construct SQL to add Employee class members to the DB, breaking
// them out into their component tables as needed
}
public List<Employee> GetEmployeeByProject(string project)
{
// Retrieve recordset of all employees on the project,
// breaking them out into instances of the Employee class
// Add each new Employee object to a list, and return the list
// to the caller.
}
}
// Specific classes for each table (or logical unit, since obviously
// most of the time we'll need to join a few tables to get what
// we want), with methods for CRUD functions
void AddSomethingToTheDatabase()
{
using (TestDataDB td = new TestDataDB())
{
td.Open(Application.StartupPath);
string NewID = td.AddTestData(txtAddMe.Text);
}
}
答案 0 :(得分:7)
您确定不想尝试Object Relational Mapper吗?
答案 1 :(得分:1)
有很多方法可以做到这一点,绝大多数OO人都不同意我的意见。
我建议你采取一种更多的关系方法,而不是为表提供类,有关系的类。在关系理论中,查询的结果就像查询中使用的关系一样;实际上你从来没有看到任何查询结果,因为即使要获取表格的内容,你需要SELECT * FROM x
,它正在应用身份函数。
所以使用您已经拥有的关系语言进行查询(构建一个框架来为您编写查询,如果您需要那么远),查询结果应该是您的类,或者,如果你不是在一种易于创建新类的语言,一些其他类型的结构(如对象)。然后,您只需直接使用这些结果。
答案 2 :(得分:0)
我会自发地想要将数据库依赖关系从对象中断开。您可以从创建一个定义TestData对象的存储方法的接口开始(在我的示例中,只有Add方法,但这当然可以扩展):
public interface ITestDataRepository
{
void Add(TestData data);
}
下一步是创建TestData类。该类的一个特性可能是接受ITestDataRepository作为构造函数中的参数,并公开Add方法:
public class TestData
{
public TestData(ITestDataRepository repository)
{
Repository = repository;
}
public ITestDataRepository Repository { get; private set; }
public string SomeData { get; set; }
public void Add()
{
if (Repository != null)
{
Repository.Add(this);
}
}
}
最后要做的是实现您要使用的数据机制。在这种情况下OleDb,但它也可以是Xml,SqlServer或任何其他形式的数据存储:
public class DbTestDataRepository : ITestDataRepository
{
const string InsertionQuery = @"INSERT INTO TEST (TESTDATA) VALUES (?)";
public void Add(TestData data)
{
using (OleDbConnection conn = DbUtil.GetConnection())
using (OleDbCommand command = new OleDbCommand(InsertionQuery, conn))
{
command.Parameters.Add("@p1", OleDbType.BSTR).Value = data.SomeData;
using (OleDbDataReader reader = command.ExecuteReader())
{
// perhaps log something?
}
}
}
}
上述设计在您的问题设计中提供了几个不同的优势:
这些只是一些简单的想法(例如,我没有测试代码而不是编译它。)