Hi All,
I'm trying to use SafeDataReader concept into a non CSLA project, basically due lack of GetXXX(string) methods in SqlDataReader. Currently I have a generic implementation I think could specially useful to CSLA:
// main load
using(GenericDataReader reader = new GenericDataReader(cm.ExecuteReader()))
{
while (reader.Read())
{
orders.Add(reader.Get<Order>()); // "GetList" pattern
//return new Order(reader); // "Get" pattern
}
}
// generic reader; interface implementation removed
public class GenericDataReader : IDataReader
{
// ... \\
public T Get<T>(string name)
{
int i = _dataReader.GetOrdinal(name);
if (_dataReader.IsDBNull(i))
return default(T);
else
return (T)_dataReader.GetValue(i);
}
public T Get<T>() where T : ILoadable, new()
{
T entity = new T();
entity.Load(this, false);
return entity;
}
}
// All business objects must inherits this interface (@BusinessBase?)
public interface ILoadable
{
void Load(GenericDataReader reader, bool deep);
}
// Sample BO 1
class Order : ILoadable
{
int id;
Customer customer; // Note
DateTime orderDate;
DateTime requiredDate;
DateTime? shippedDate;
List<OrderDetail> orderDetails;
public Order(){ }
public Order(GenericDataReader reader)
{
Load(reader, true);
}
#region ILoadable Members
public void Load(GenericDataReader reader, bool deep)
{
id = reader.Get<int>("OrderID");
customer = reader.Get<Customer>(); // Note
orderDate = reader.Get<DateTime>("OrderDate");
requiredDate = reader.Get<DateTime>("OrderRequiredDate");
shippedDate = reader.Get<DateTime?>("OrderShippedDate");
if (deep && reader.NextResult())
{
orderDetails = new List<OrderDetail>();
while (reader.Read())
{
orderDetails.Add(reader.Get<OrderDetail>());
}
}
}
#endregion
}
// Sample BO 2
class Customer : ILoadable
{
string customerID;
List<Order> orders;
public Customer(){ }
internal Customer(GenericDataReader reader)
{
Load(reader, true);
}
#region ILoadable Members
public void Load(GenericDataReader reader, bool deep)
{
customerID = reader.Get<string>("CustomerID");
if (deep && reader.NextResult())
{
orders = new List<Order>();
while (reader.Read())
{
orders.Add(reader.Get<Order>());
}
}
}
#endregion
}
What do you think? Are there any major drawback with this model I'm missing?
Best regards,
Rubens
Hi Rubens,
On a first look it looks like an elegant solution. And this is completely OK if you are sure that this app is going to be built only with ADO.NET.
However if this is going to be an ongoing project, that perhaps in the future might migrate the Data Acces Layer code to some ORM Technology, like NHiberbate, Linq or Entity Framework, then the tight coupling of your business objects with the IDataReader (or GenericDataReader) might prove as a migration bottleneck. In other words you have to change the signature of each of your BOs to migrate to another storage technology.
There is a reason why Rocky has not implemented something like that in Csla as much as it appears more readable and simpler than what we have now.
Those are my 2c
Nermin
RubensFarias:Hi All,
I'm trying to use SafeDataReader concept into a non CSLA project, basically due lack of GetXXX(string) methods in SqlDataReader. Currently I have a generic implementation I think could specially useful to CSLA:
// main load
using(GenericDataReader reader = new GenericDataReader(cm.ExecuteReader()))
{
while (reader.Read())
{
orders.Add(reader.Get<Order>()); // "GetList" pattern
//return new Order(reader); // "Get" pattern
}
}// generic reader; interface implementation removed
public class GenericDataReader : IDataReader
{
// ... \\public T Get<T>(string name)
{
int i = _dataReader.GetOrdinal(name);
if (_dataReader.IsDBNull(i))
return default(T);
else
return (T)_dataReader.GetValue(i);
}public T Get<T>() where T : ILoadable, new()
{
T entity = new T();
entity.Load(this, false);
return entity;
}
}// All business objects must inherits this interface (@BusinessBase?)
public interface ILoadable
{
void Load(GenericDataReader reader, bool deep);
}// Sample BO 1
class Order : ILoadable
{
int id;
Customer customer; // Note
DateTime orderDate;
DateTime requiredDate;
DateTime? shippedDate;
List<OrderDetail> orderDetails;public Order(){ }
public Order(GenericDataReader reader)
{
Load(reader, true);
}#region ILoadable Members
public void Load(GenericDataReader reader, bool deep)
{
id = reader.Get<int>("OrderID");
customer = reader.Get<Customer>(); // Note
orderDate = reader.Get<DateTime>("OrderDate");
requiredDate = reader.Get<DateTime>("OrderRequiredDate");
shippedDate = reader.Get<DateTime?>("OrderShippedDate");
if (deep && reader.NextResult())
{
orderDetails = new List<OrderDetail>();
while (reader.Read())
{
orderDetails.Add(reader.Get<OrderDetail>());
}
}
}#endregion
}// Sample BO 2
class Customer : ILoadable
{
string customerID;
List<Order> orders;public Customer(){ }
internal Customer(GenericDataReader reader)
{
Load(reader, true);
}#region ILoadable Members
public void Load(GenericDataReader reader, bool deep)
{
customerID = reader.Get<string>("CustomerID");
if (deep && reader.NextResult())
{
orders = new List<Order>();
while (reader.Read())
{
orders.Add(reader.Get<Order>());
}
}
}#endregion
}What do you think? Are there any major drawback with this model I'm missing?
Best regards,
Rubens
Hi Nermin,
In my specific case, there are no signal about ORM mapping in a closer future.
But you're right. I'll think about that and try to work around it.
Thank you for your time,
Rubens
Copyright (c) Marimer LLC