r_khanipour wrote:
I call previous method like this:
ConvertStoredProcedureToCollection<Table1TEntity,Table1TCollection>(RetrievalProcedures.GetGetTable1SpCallAsQuery(null),null);
And that query is a "SELECT * FROM Table1"
Otis,you see, this is a common issue to use the ordinal of a Table, because we use "SELECT *" in database and so the ordinal of output is like a Table.
I know, but that doesn't mean things can't break due to that, and IF they do, you also should look into why that is.
you say Resultset but why we create EntityCollection? if we use proc for security issue to fill EntityCollection how could we????? we should use template????? we should arrange alphabetic for every entity?????
Shouldn't be a way to fill a EntityCollection by a proc without difficulty????
I don't know but i think, it's NEEDED!
Thanks So Much and Best Wishes for you.
Rahman
We change things sometimes, and they break code sometimes. I'll give you a piece of code below which might help. I haven't test it in full, so it might fail somewhere but it should give you an idea how to fix it (my test with an entity returning proc worked). I gave you a hint how to fix it too with a template (which generates code for you to produce the projectors for you). Anyway, since you use this method you posted above, it's not hard to fix it. See below.
**NOTE: ** this one works for Selfservicing only. For adapter, a similar method has to be added to the DataAccessAdapter class, which obtains the persistence info objects first.
private TEntityCollection ConvertStoredProcedureToCollection<TEntityObject, TEntityCollection>(IRetrievalQuery query, Transaction transactionManager)
where TEntityObject : EntityBase, new()
where TEntityCollection : EntityCollectionBase<TEntityObject>, new()
{
//Create new instances of the EntityObject and EntityCollection.
TEntityObject entityObject = new TEntityObject();
TEntityCollection entityCollection = new TEntityCollection();
//Get all the Fields of the EntityObject. These fields are necessary for fetching all the data from the resultset.
IEntityFields entityFields = entityObject.Fields;
using (query)
{
//Get the resultset of the Stored Procedure as an IDataReader.
TypedListDAO dao = new TypedListDAO();
using (IDataReader reader = dao.GetAsDataReader(transactionManager, query, CommandBehavior.CloseConnection))
{
// create an ordinal lookup per field in the resultset.
Dictionary<string, int> fieldIndexLookup = new Dictionary<string, int>();
for(int i=0;i<reader.FieldCount;i++)
{
fieldIndexLookup[reader.GetName(i)] = i;
}
//Create a new instance of List<IDataValueProjector>. In this the values which will be fetched will be stored.
List<IDataValueProjector> valueProjectors = new List<IDataValueProjector>(entityFields.Count);
foreach (EntityField entityField in entityFields)
{
//Put each entityField in List<IDataValueProjector>.
int index = 0;
if(!fieldIndexLookup.TryGetValue(entityField.SourceColumnName, out index))
{
index = entityField.FieldIndex;
}
valueProjectors.Add(new DataValueProjector(entityField.Alias, index, entityField.DataType));
}
//Create the projector and fill the collection.
DataProjectorToIEntityCollection projector = new DataProjectorToIEntityCollection(entityCollection);
dao.GetAsProjection(valueProjectors, projector, reader);
reader.Close();
}
}
return entityCollection;
}
Note 2: you might want to cache the lookup dictionaries, as they're always the same.