Return Custom Object <List T> from Entity framework and assign to Object Data Source

Shokwave picture Shokwave · Oct 27, 2011 · Viewed 21.1k times · Source

I need some guidance with an issue, I am using Entity Framework 4.0, I have a DAL and BLL and am binding to ObjectDataSource on the page.

I had to write a stored procedure using PIVOT and dynamic SQL to return the data from multiple entities the way I want. Now I am trying to figure out how can I get Entity Framework to return a custom object that I can bind to my ObjectDataSource on the page, I NEED to use a custom object or a dynamic object since the stored procedure can return any number of columns so I can't use a strongly typed class or entity and I need to be also able to bind this with an ObjectDataSource.

Can someone point out a good way to do this and how to define my function? With some code examples please.

I read that I should try to use List<T> for returning an object since EF does not support returning datatables/datasets, I have the following so far but I know this isn't correct.

I have not worked with generics much, if you could point out how to do this I'm sure this would be helpful for a lot of people. Please provide code examples for the function and how to bind ObjectDataSource to the return object?

Your help is greatly appreciated!!

Thanks for your help Richard this is what my function looks like right now based on your suggestion for using DbDataRecord

C# function for ObjectDataSource in DAL

public List<DbDataRecord> GetData(int product_id)
{
    List<DbDataRecord> availableProducts = new List<DbDataRecord>();

    var groupData = context.ExecuteStoreQuery<DbDataRecord>("exec 
  spGetProducts @ProductID={0}", product_id);

    availableProducts = groupData.ToList<DbDataRecord>();

    return availableProducts;
}

ObjectDataSource in ASPX page

<asp:ObjectDataSource ID="ODSProductAvailability" runat="server"
        TypeName="Project.BLL.ProductBL" 
        SelectMethod="GetData"  >
     <SelectParameters>
        <asp:SessionParameter Name="product_id" SessionField="ProductID" />
     </SelectParameters>
</asp:ObjectDataSource>

Right now I'm getting this error when I access the page:

The result type 'System.Data.Common.DbDataRecord' may not be abstract and must include a default constructor

Is this because the ExecuteStoreQuery expects to be defined class or entity? How can I just create an object based on the stored procedure results and assign it that?

Answer

jrummell picture jrummell · Oct 27, 2011

If you already have an Entity type that matches your proc return type, use it as the type parameter.

public List<MyEntity> GetData<MyEntity>(int product_id) where T : class 
{

    List<MyEntity> myList = new List<MyEntity>(); 

    var groupData = context.ExecuteStoreQuery<MyEntity>("exec 
    spGetProductsByGroup @ProductID={0}", product_id);

    return myList;
}

Otherwise you could use an ADO.NET DataReader to build the list manually.

using (SqlConnection connection = new SqlConnection("your connection string"))
{
    SqlCommand command = new SqlCommand(
      "exec spGetProductsByGroup @ProductID",
      connection);
    command.Parameters.Add(product_id);

    connection.Open();

    SqlDataReader reader = command.ExecuteReader();

    List<ProcType> list = new List<ProcType>();
    if (reader.HasRows)
    {
        while (reader.Read())
        {
            list.Add(new ProcType(){Property1 = reader.GetInt32(0), Property1 = reader.GetString(1));
        }
    }
    reader.Close();

    return list;
}