使用反射和属性的 OO 持久化方法,在 C# 中






4.19/5 (33投票s)
2003年6月10日
2分钟阅读

114362

957
描述了如何使用 C# 属性、ADO.NET 和 C# 将对象持久化到数据库。
引言
过去作为 J2EE 开发者并且是 OOD 的忠实粉丝,几个月前我开始使用 .NET。现在我已经看到了 .NET 数据持久化方法,DataSet
、DataReader
和 ADO.NET 中的 DataAdapter
,我认为在处理表中多个记录时非常强大,但我仍然喜欢在我的设计中使用业务对象,所以我为 .NET 编写了一个小的持久化框架。
过去使用 JDO,我考虑为每个 BO 创建一个 XML 描述,将其映射到数据库表,但我发现更好的方法是使用 .NET 属性。我在 Internet 上找到了一篇文章,其中包含使用属性实现此目的的示例。
假设我们有一个名为 User
的 BO
public class User
{
public User(){}
private long _id;
private string _name;
private string _username;
private string _password;
//for each of these fields we have a Property
public long UserID {
set{_id = value;}
get {return _id;}
}
//etc
…
}
现在让我们将其映射到数据库
[DBTable("Users","dbo")]
[Serializable]
public class User
{
public User(){}
private long _id;
private string _name;
private string _username;
private string _password;
[DBPrimaryKeyField("ID_User",DbType.Int16)]
[DBColumn("ID_User",DbType.Int16,false)]
public long UserID
{
set{_id = value;}
get {return _id;}
}
[DBColumn("Name",DbType.String,true)]
public string Name
{
//set, get
}
[DBColumn("Username",DbType.String,false)]
public string Username
{
//set, get
}
[DBColumn("Password",DbType.String,false)]
public string Password
{
//set, get
}
}
我们有 3 个属性类 DBTable
、DBPrimaryKey
、DBColumn
。让我们解释一下每个类的作用。
DBTable(string tableName, string databaseOwner)
将业务对象映射到数据库表
DBPrimaryKey(string pkFieldName, DBType pkFieldType, bool isAutoIncrement)
将
Primary
列映射到 BO 属性DBColumn(string tableFieldName, DBType fieldType, bool allowsNulls)
将表列映射到 BO 属性。
现在让我们看看可以使用 BO 做些什么。这是通过 IPersistenceService
接口完成的。
public interface IPersistenceService
{
object Create(Object o, Type objectType);
void Update(Object o, Type objectType);
void Delete(Object id, Type objectType);
int Count(string condition, Type objectType);
Object GetObject(Object id, Type objectType);
void LoadDataSet(DataSet dataSet, String sqlQuery);
void LoadDataSet(DataSet dataSet, String sqlQuery, String tableName);
object Create(SqlConnection con, Object o, Type objectType);
void Update(SqlConnection con,Object o, Type objectType);
void Delete(SqlConnection con,Object id, Type objectType);
int Count(SqlConnection con,string condition, Type objectType);
Object GetObject(SqlConnection con,Object id, Type objectType);
void LoadDataSet(SqlConnection con,DataSet dataSet, String sqlQuery);
void LoadDataSet(SqlConnection con,DataSet dataSet, String sqlQuery,
String tableName);
SqlConnection GetConnection();
void CloseConnection(SqlConnection con);
}
我们有一个此接口的工厂来获取实现。 在这种情况下,该实现是针对 PersistenceServiceImpl
中的 SQL Server 完成的。我们得到一个实现
String connectionString = “…”;
IPersistenceService ps = PersistenceServiceFactory.getPS(connectionString);
现在让我们创建一个 User
并持久化它。
User u = new User();
u.Name = "Dan Bunea";
u.Password = "myusername";
u.Password = "mypassword";
//obtain id for the new user in the
long id = (long)ps.Create(u,typeof(User));
或者只是:(如果您不需要为对象获取 ID)
ps.Create(u,typeof(User));
现在我们在 Users
表中有一个用户,让我们检索它来看看是如何完成的。
User U2 = (User)ps.GetObject(id,typeof(User));
让我们更新它并保存更改。
U2.Name = "Dan Bunea Updates";
U2.Password = "newusername";
U2.Password = "newpassword";
P2s.Update(U2,typeof(User));
简单 J,不是吗?现在让我们删除它。
Ps.Delete(id,typeof(User));
我还包括了一些轻松加载 DataSet
对象的方法,但如果您有更多需要使用相同连接的操作,也可以使用。 假设我们希望在一个连接上执行所有这些操作
SqlConnection con = ps.GetConnection();
User u = new User();
u.Name = "Dan Bunea";
u.Password = "myusername";
u.Password = "mypassword";
object id = (long)ps.Create(con,u,typeof(User));
User U2 = (User)ps.GetObject(con,id,typeof(User));
U2.Name = "Dan Bunea Updates";
U2.Password = "newusername";
U2.Password = "newpassword";
P2s.Update(con,U2,typeof(User));
Ps.Delete(con,id,typeof(User));
ps.CloseConnection(con);
让我们谈谈性能。 对于每个 BO,用户不必担心 INSERT
、UPDATE
、DELETE
和 SELECT
(对于 pk)查询。 它们是使用对象中指定的属性通过代码自动生成的。 每个 BO 的每个语句仅生成一次,然后与其参数一起缓存。 下次用户执行相同的操作时,查询将从缓存中获取,其参数也会获取,并使用反射为每个参数赋值,然后执行查询。
特别感谢那些撰写其他文章帮助我写这篇文章的人,并希望这是一篇愉快且有用的阅读,我在这里结束我的小文章。