2008-09-02 4 views
4

Предположим, что я создаю уровень доступа к данным для приложения. Обычно у меня есть определение класса для каждого типа объекта, который хранится в базе данных. Конечно, фактический доступ к данным извлекает данные в виде набора данных, типизированного или нетипизированного набора данных или аналогичных данных, обычно с данными, необходимыми для создания одного объекта в строке в результатах.Создать объект из строки базы данных

Как вы собираетесь создавать экземпляры объектов в слое данных? Будет ли конструктор, принимающий datarow? Если да, то как бы вы сделали этот тип безопасности? Или у вас есть список конструкторов из одного параметра для каждого поля, которое вы хотите создать, даже если может быть много полей? Вы отметили бы этот конструктор «внутренним»?

ответ

3

Я настоятельно рекомендую вам использовать инструмент ORM. Даже простые проекты могут использовать ORM быстро и спокойно ... в частности, посмотрите на инструмент CastleActiveRecord (который находится поверх NHibernate, чтобы упростить объявление модели).

7

Если вы не довольны DataRow или SqlDataReader, вы должны посмотреть на систему ORM, такую ​​как Linq to Sql или nHibernate, вместо того, чтобы самостоятельно изобретать колесо.

(Кстати, это называется «ActiveRecord» шаблон)

0

Будут ли поддерживаться более сложные запросы в качестве источника данных? Это может, например, присоединиться к нескольким другим таблицам, хотя бы для определения того, какие записи должны быть возвращены в конкретной ситуации? И позволят ли вы добавить свои собственные методы в классы, которые они используют?

2

Я достиг этого, используя отражение. Где я называю столбец из оператора Select объекта.

Предполагается, что у вас есть вспомогательный класс Templated. Если вы хотите поместить его на объект самостоятельно, вы можете просто заменить все 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; 
} 
1

@Joel (ре: сложные запросы, соединения, и т.д.)

NHibernate и замок ActiveRecord инструмент может обрабатывать очень сложные запросы и присоединяется с помощью классовых отношений и а тщательный класс «Выражение» (который вы можете добавить к методам запросов) или использование «языка запросов гибернации» (HQL).

Вы можете использовать любую из этих подробностей Google, отметьте официальное documentation или посмотрите потрясающие видеоролики Summer of NHibernate.

1

В качестве альтернативы NHibernate & Замок вы можете посмотреть на SubSonic. Это также использует ActiveRecord, но это скорее нож швейцарской армии, чем NHibernate.

EDIT:

Вот sample от дозвуковых документации:

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); 

И некоторые дополнительные examples:

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); 

И некоторые Wildcard methods:

[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); 
     } 
Смежные вопросы