<p>Let's say I'm building a data access layer for an application.  Typically I have a class definition for a each kind of object that is stored in the database.  Of course, the actual data access retrieves data in the form of a datareader, typed or untyped dataset, or similar, usually with the data needed to create one object per row in the results.</p>

<p>How would you go about creating your object instances in the data layer?  Would have a constructor that accepts a datarow?  If so, how would you make that type-safe?  Or would you have your constructor list out one parameter for each field you want to instantiate, even if there could be many fields?  Would you mark this constructor 'internal'?</p>

[{'answer_id': 40309, 'author': 'Eric Z Beard', 'author_id': 1219, 'author_profile': 'https://Stackoverflow.com/users/1219', 'pm_score': 3, 'selected': False, 'text': '<p>If you aren\'t content with DataRow or SqlDataReader, you should look at an ORM system like Linq to Sql or nHibernate, instead of re-inventing the wheel yourself.</p>\n\n<p>(By the way, this is called the "ActiveRecord" pattern)</p>\n'}, {'answer_id': 40321, 'author': 'Anthony Mastrean', 'author_id': 3619, 'author_profile': 'https://Stackoverflow.com/users/3619', 'pm_score': 3, 'selected': True, 'text': '<p>I highly encourage you to use an ORM tool. Even simple projects can make use of ORM quickly and quietly... in particular, look at <a href="http://www.castleproject.org/" rel="nofollow noreferrer">Castle</a>\'s <a href="http://www.castleproject.org/activerecord/" rel="nofollow noreferrer">ActiveRecord</a> tool (which sits on top of NHibernate to simplify model declaration).</p>\n'}, {'answer_id': 41034, 'author': 'David Basarab', 'author_id': 2469, 'author_profile': 'https://Stackoverflow.com/users/2469', 'pm_score': 2, 'selected': False, 'text': '<p>I have accomplished this by using reflection.  Where I name the column from the Select statement of the object.</p>\n\n<p>This assumes you have a Templated helper class.  If you want to put it on the object yourself you can just replace all the T with the object.</p>\n\n<p>This is an example:</p>\n\n<pre><code>private T ObjectFromRow(DataRow row)\n{\n    Type t = typeof(T);\n\n    T newObj = (T)Activator.CreateInstance(t);\n\n\n    System.Reflection.PropertyInfo[] properties = t.GetProperties();\n\n    for (int i = 0; i &lt; properties.Length; i++)\n    {\n        if (!properties[i].CanWrite)\n        {\n            continue;\n        }\n\n        if (!row.Table.Columns.Contains(properties[i].Name))\n        {\n            continue;\n        }\n\n        if (row[properties[i].Name] == DBNull.Value)\n        {\n            continue;\n        }\n\n        if (properties[i].PropertyType == typeof(string))\n        {\n            properties[i].SetValue(newObj, row[properties[i].Name], null);\n        }\n        else if (properties[i].PropertyType == typeof(double))\n        {\n            properties[i].SetValue(newObj, double.Parse(row[properties[i].Name].ToString()), null);\n        }\n        else if (properties[i].PropertyType == typeof(int))\n        {\n            properties[i].SetValue(newObj, int.Parse(row[properties[i].Name].ToString()), null);\n        }\n        else if (properties[i].PropertyType == typeof(DateTime))\n        {\n            properties[i].SetValue(newObj, DateTime.Parse(row[properties[i].Name].ToString()), null);\n        }\n        else if (properties[i].PropertyType == typeof(bool))\n        {\n            properties[i].SetValue(newObj, bool.Parse(row[properties[i].Name].ToString()), null);\n        }\n    }\n\n    return newObj;\n}\n</code></pre>\n'}, {'answer_id': 41563, 'author': 'Anthony Mastrean', 'author_id': 3619, 'author_profile': 'https://Stackoverflow.com/users/3619', 'pm_score': 1, 'selected': False, 'text': '<p>@Joel (re: complex queries, joins, etc)</p>\n\n<p>The NHibernate and Castle ActiveRecord tool can handle very complex queries and joins via class relationships and a thorough \'Expression\' class (which you can add to the query methods) or the use of the \'Hibernate Query Language\' (HQL).</p>\n\n<p>You can Google any of these details, check the official <a href="http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/" rel="nofollow noreferrer">documentation</a>, or see the awesome <a href="http://www.summerofnhibernate.com/" rel="nofollow noreferrer">Summer of NHibernate</a> screencasts.</p>\n'}, {'answer_id': 196254, 'author': 'David Robbins', 'author_id': 19799, 'author_profile': 'https://Stackoverflow.com/users/19799', 'pm_score': 1, 'selected': False, 'text': '<p>As an alternative to NHibernate &amp; Castle you can take a look at <a href="http://subsonicproject.com/" rel="nofollow noreferrer">SubSonic</a>.  This also uses ActiveRecord but is more of a Swiss Army knife than NHibernate. </p>\n\n<p>EDIT:</p>\n\n<p>Here is a <a href="http://subsonicproject.com/querying/select-queries/" rel="nofollow noreferrer">sample</a> from the SubSonic documentation:</p>\n\n<pre><code>Simple Select with string columns\n\n            int records = new Select("productID").\n                 From("Products").GetRecordCount();\n\n            Assert.IsTrue(records == 77);\n\nSimple Select with typed columns\n\n            int records = new Select(Product.ProductIDColumn, Product.ProductNameColumn).\n                From&lt;Product&gt;().GetRecordCount();\n            Assert.IsTrue(records == 77);\n</code></pre>\n\n<p>And some further <a href="http://subsonicproject.com/querying/aggregate-queries/" rel="nofollow noreferrer">examples</a>:</p>\n\n<pre><code>Standard Deviation\n\n    const double expected = 42.7698669325723;\n\n    // overload #1\n    double result = new\n        Select(Aggregate.StandardDeviation("UnitPrice"))\n        .From(Product.Schema)\n        .ExecuteScalar&lt;double&gt;();\n    Assert.AreEqual(expected, result);\n\n    // overload #2\n    result = new\n        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn))\n        .From(Product.Schema)\n        .ExecuteScalar&lt;double&gt;();\n    Assert.AreEqual(expected, result);\n\n    // overload #3\n    result = new\n        Select(Aggregate.StandardDeviation("UnitPrice", "CheapestProduct"))\n        .From(Product.Schema)\n        .ExecuteScalar&lt;double&gt;();\n    Assert.AreEqual(expected, result);\n\n    // overload #4\n    result = new\n        Select(Aggregate.StandardDeviation(Product.UnitPriceColumn, "CheapestProduct"))\n        .From(Product.Schema)\n        .ExecuteScalar&lt;double&gt;();\n    Assert.AreEqual(expected, result);\n</code></pre>\n\n<p>And some <a href="http://subsonicproject.com/querying/subsonic-added-wildcard-methods/" rel="nofollow noreferrer">Wildcard methods</a>:</p>\n\n<pre><code> [Test]\n        public void Select_Using_StartsWith_C_ShouldReturn_9_Records() {\n\n\n            int records = new Select().From&lt;Product&gt;()\n                .Where(Northwind.Product.ProductNameColumn).StartsWith("c")\n                .GetRecordCount();\n            Assert.AreEqual(9, records);\n        }\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/40302', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3043/']