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

通过反射解析 DataSet

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.18/5 (6投票s)

2009 年 9 月 1 日

CPOL

2分钟阅读

viewsIcon

26731

downloadIcon

336

本文展示了如何将关系数据模型与对象设计模型绑定。

引言

很多时候,我需要将关系模型与对象设计模型绑定。有时,我使用 NHibernate 创建应用程序引擎,有时我使用 ADO.NET Entity Framework,但大多数情况下我不得不使用 DataTable 并围绕 DataTable 对象创建包装器,其中包含大量的 "switch" 语句。

NHibernate 在开发 "桌面" 或 "Web" 应用程序时是一个不错的选择,但它在 Windows Mobile 上的 Compact Framework 中无法工作,因为 CF 不支持动态编译。 ADO.NET Entity Framework 是为 .NET 3.5 风格设计的 "新" 应用程序的一个不错的选择。 在本文中,我想展示如何解析 DataSet 并从中创建对象。 您可以从本文顶部的链接下载源代码并使用这个小库。

背景

要测试应用程序,您应该安装 SQL Compact 3.5 和 .NET 3.5。 您也可以在 .NET 2.0 中使用此库,但您应该替换 LINQ 用法。

Using the Code

为了展示它的工作原理,我创建了一个包含 3 个表的简单数据库。 该系统的核心是泛型类 BusinessObject<T>。 该类包含必要的 static 方法,允许获取派生对象。

public static List<T> Get(DataSet dataSet) 
public static List<T> Get(DataTable dataTable) 
public static T GetOne(DataSet dataSet)	
public static T GetOne(DataTable dataTable) 
public static T GetOne(DataRow row) 

绑定对象的步骤

  1. 创建一个从 BusinessObject<T> 派生的新类。
  2. 创建与数据库字段对应的属性,并使用 "BoFieldAttribute" 标记它们。
  3. 如果表与其他表有关系,则创建新的属性并使用 BoChildAttribute 标记它们。

BoFieldAttribute - 具有带参数 "name" 的构造函数。 您应该放置一个与 DataTable 中的 ColumnName 对应的 string

这是一个例子。

class Customer : BusinessObject<Customer>
    {
        [BoField(CustomerNames.Id)]
        public int Id { get; set; }
        [BoField(CustomerNames.Name)]
        public string Name { get; set; }
    }
class Product : BusinessObject<Product>
    {
        [BoField(ProductNames.Id)]
        public int Id { get; set; }
        [BoField(ProductNames.Title)]
        public string Title { get; set; }
    } 
    class OrderLine : BusinessObject<OrderLine>
    {
        [BoField(OrderLineNames.Id)]
        public int Id { get; set; }
        [BoField(OrderLineNames.ProductId)]
        public int ProductId { get; set; }
        [BoField(OrderLineNames.CustomerId)]
        public int CustomerId { get; set; }

        [BoChild]
        public Customer Customer { get; set; }
        [BoChild]
        public Product Product { get; set; }
    }  

然后使用起来非常简单。 只需调用 "Get" 方法之一即可。

  const string sql =
                @"SELECT * FROM OrderLine INNER JOIN Customer 
				ON Customer.C_Id = OrderLine.O_CustomerId
						INNER JOIN Product 
				ON Product.P_Id = OrderLine.O_ProductId";
  DataTable dataTable = DatabaseLayer.Instance.ExecuteTable(sql);
  lwOrderLines.ItemsSource = OrderLine.Get(dataTable);

工作原理

当您调用 "Get" 方法之一时

  1. BusinessObject 类创建泛型类型的新对象。
  2. 搜索标记的属性并将新值从 DataTable 分配给属性。

还有一件事我想描述的是 GetConvertedObject 方法

protected virtual object GetConvertedObject(Type type, object o)
        {
            if (type.IsEnum) return Enum.Parse(type, o.ToString(),true);
            if (type == typeof(byte[])) return o.Equals(DBNull.Value) ? null : o;
            if (type == typeof(DateTime)) return ToDateTime(o);
            if (type == typeof(string)) return ToString(o);
            if (type == typeof(int)) return ToInt32(o);
            if (type == typeof(long)) return ToInt64(o);
            if (type == typeof(DateTime)) return ToDateTime(o);
            if (type == typeof(Double)) return ToDouble(o);
            if (type == typeof(Boolean))
                return o.ToString().Trim() == "1" 
                           ? true : o.ToString().Trim() == "0" 
                                        ? false : type.ParseValue(o); 
            return type.ParseValue(o);
        }   

此方法是虚拟的,可以在派生类中重写。 如果我们希望在解析操作中具有转换数据的可能性,它非常有用。 例如,我们可以将数据作为图像类型存储在 SQL Compact 中,并将其转换为 System.Drawing.Image ImageSource (WPF 版本)。

历史

  • 2009 年 9 月 1 日:初始发布
© . All rights reserved.