65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.19/5 (33投票s)

2003年6月10日

2分钟阅读

viewsIcon

114362

downloadIcon

957

描述了如何使用 C# 属性、ADO.NET 和 C# 将对象持久化到数据库。

引言

过去作为 J2EE 开发者并且是 OOD 的忠实粉丝,几个月前我开始使用 .NET。现在我已经看到了 .NET 数据持久化方法,DataSetDataReader 和 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 个属性类 DBTableDBPrimaryKeyDBColumn。让我们解释一下每个类的作用。

  • 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,用户不必担心 INSERTUPDATEDELETESELECT(对于 pk)查询。 它们是使用对象中指定的属性通过代码自动生成的。 每个 BO 的每个语句仅生成一次,然后与其参数一起缓存。 下次用户执行相同的操作时,查询将从缓存中获取,其参数也会获取,并使用反射为每个参数赋值,然后执行查询。

特别感谢那些撰写其他文章帮助我写这篇文章的人,并希望这是一篇愉快且有用的阅读,我在这里结束我的小文章。

© . All rights reserved.