.net 从数据库行创建对象

.net 从数据库行创建对象,.net,.net,假设我正在为应用程序构建数据访问层。通常,对于存储在数据库中的每种对象,我都有一个类定义。当然,实际的数据访问以datareader、类型化或非类型化数据集或类似的形式检索数据,通常使用在结果中每行创建一个对象所需的数据 如何在数据层中创建对象实例?是否有接受数据行的构造函数?如果是这样,您将如何确保该类型的安全性?或者让构造函数为每个要实例化的字段列出一个参数,即使可能有许多字段?你会将此构造函数标记为“内部”吗?如果你不满足于DataRow或SqlDataReader,你应该看看像Linq

假设我正在为应用程序构建数据访问层。通常,对于存储在数据库中的每种对象,我都有一个类定义。当然,实际的数据访问以datareader、类型化或非类型化数据集或类似的形式检索数据,通常使用在结果中每行创建一个对象所需的数据


如何在数据层中创建对象实例?是否有接受数据行的构造函数?如果是这样,您将如何确保该类型的安全性?或者让构造函数为每个要实例化的字段列出一个参数,即使可能有许多字段?你会将此构造函数标记为“内部”吗?

如果你不满足于DataRow或SqlDataReader,你应该看看像Linq to Sql或nHibernate这样的ORM系统,而不是自己重新发明轮子


(顺便说一下,这被称为“ActiveRecord”模式)

我强烈建议您使用ORM工具。即使是简单的项目也可以快速、安静地使用ORM。。。特别是,看看的工具(它位于NHibernate之上,用于简化模型声明)。

我已经通过使用反射实现了这一点。其中,我从对象的Select语句中命名列

这假设您有一个模板化的助手类。如果你想自己把它放在物体上,你可以用物体替换所有的T

这是一个例子:

private T ObjectFromRow(DataRow row)
{
    Type t = typeof(T);

    T newObj = (T)Activator.CreateInstance(t);


    System.Reflection.PropertyInfo[] properties = t.GetProperties();

    for (int i = 0; i < properties.Length; i++)
    {
        if (!properties[i].CanWrite)
        {
            continue;
        }

        if (!row.Table.Columns.Contains(properties[i].Name))
        {
            continue;
        }

        if (row[properties[i].Name] == DBNull.Value)
        {
            continue;
        }

        if (properties[i].PropertyType == typeof(string))
        {
            properties[i].SetValue(newObj, row[properties[i].Name], null);
        }
        else if (properties[i].PropertyType == typeof(double))
        {
            properties[i].SetValue(newObj, double.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(int))
        {
            properties[i].SetValue(newObj, int.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(DateTime))
        {
            properties[i].SetValue(newObj, DateTime.Parse(row[properties[i].Name].ToString()), null);
        }
        else if (properties[i].PropertyType == typeof(bool))
        {
            properties[i].SetValue(newObj, bool.Parse(row[properties[i].Name].ToString()), null);
        }
    }

    return newObj;
}
private T ObjectFromRow(DataRow)
{
类型t=类型(t);
T newObj=(T)Activator.CreateInstance(T);
System.Reflection.PropertyInfo[]properties=t.GetProperties();
for(int i=0;i
@Joel(关于:复杂查询、连接等)

NHibernate和Castle ActiveRecord工具可以通过类关系和彻底的“表达式”类(可以添加到查询方法中)或使用“Hibernate查询语言”(HQL)处理非常复杂的查询和连接


您可以通过谷歌搜索这些详细信息,查看官方网站,或查看精彩的屏幕广播。

作为NHibernate&Castle的替代方案,您可以查看。这也使用了ActiveRecord,但更像是一把瑞士军刀,而不是NHibernate

编辑:

以下是亚音速文件中的一个示例:

Simple Select with string columns

            int records = new Select("productID").
                 From("Products").GetRecordCount();

            Assert.IsTrue(records == 77);

Simple Select with typed columns

            int records = new Select(Product.ProductIDColumn, Product.ProductNameColumn).
                From<Product>().GetRecordCount();
            Assert.IsTrue(records == 77);
使用字符串列进行简单选择
int records=new Select(“productID”)。
来自(“产品”).GetRecordCount();
Assert.IsTrue(记录==77);
使用类型化列进行简单选择
int records=new Select(Product.ProductIDColumn、Product.ProductNameColumn)。
From().GetRecordCount();
Assert.IsTrue(记录==77);
还有一些:

标准差
预期常数双=42.7698669325723;
//超载#1
双结果=新结果
选择(累计标准偏差(“单价”))
.From(Product.Schema)
.ExecuteScalar();
断言.AreEqual(预期、结果);
//超载#2
结果=新的
选择(聚合.标准偏差(产品.单价列))
.From(Product.Schema)
.ExecuteScalar();
断言.AreEqual(预期、结果);
//超载#3
结果=新的
选择(聚合标准偏差(“单价”、“最便宜的产品”))
.From(Product.Schema)
.ExecuteScalar();
断言.AreEqual(预期、结果);
//超载#4
结果=新的
选择(聚合.标准偏差(Product.unitprice列,“最便宜的产品”))
.From(Product.Schema)
.ExecuteScalar();
断言.AreEqual(预期、结果);
还有一些:

[测试]
public void Select_Using_StartsWith_C_should返回_9_记录(){
int records=new Select().From()
.Where(Northwind.Product.ProductNameColumn).StartsWith(“c”)
.GetRecordCount();
断言。AreEqual(9,记录);
}
Standard Deviation

    const double expected = 42.7698669325723;

    // overload #1
    double result = new
        Select(Aggregate.StandardDeviation("UnitPrice"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #2
    result = new
        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #3
    result = new
        Select(Aggregate.StandardDeviation("UnitPrice", "CheapestProduct"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);

    // overload #4
    result = new
        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn, "CheapestProduct"))
        .From(Product.Schema)
        .ExecuteScalar<double>();
    Assert.AreEqual(expected, result);
 [Test]
        public void Select_Using_StartsWith_C_ShouldReturn_9_Records() {


            int records = new Select().From<Product>()
                .Where(Northwind.Product.ProductNameColumn).StartsWith("c")
                .GetRecordCount();
            Assert.AreEqual(9, records);
        }