Wrox Programmer Forums
|
ASP.NET 3.5 Professionals If you are an experienced ASP.NET programmer, this is the forum for your 3.5 questions. Please also see the Visual Web Developer 2008 forum.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the ASP.NET 3.5 Professionals section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old January 26th, 2009, 05:49 AM
Registered User
Points: 38, Level: 1
Points: 38, Level: 1 Points: 38, Level: 1 Points: 38, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default EDMX

dear friends
do any one have idea about edmx concepts.If so please share

...How to call the stored procedure using edmx etc.....
 
Old January 26th, 2009, 08:17 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,093
Thanks: 1
Thanked 12 Times in 11 Posts
Default

Here's a simple example of how to map a stored procedure in an Entity Framework Data Model. I'm using the Northwind Customers table, and a simple sproc to fetch a list of Customers (I don't think the Entity Framework yet supports automatic code generation for sprocs that return scalar values).
Code:
CREATE PROCEDURE GetCustomerList
AS
SELECT
   CustomerID,
   CompanyName,
   ContactName,
   ContactTitle,
   Address,
   City,
   Region,
   PostalCode,
   Country,
   Phone,
   Fax
FROM
   Customers
1. Add a new Entity Data Model as you normally would using the Entity Data Model Wizard. Target a copy of the Northwind database (including the stored procedure listed above). When prompted just select the Customers table and the GetCustomerList sproc from the respective tree nodes.

2. I now have a Northwind.edmx file that displays a Customers entity in the designer (I singularize generated entity names, so mine is now called Customer).

3. With the designer displayed, find the Model Browser tab. The tab displays 2 nodes: NorthwindModel and NorthwindModel.Store. NorthwindModel is giving you a graphical representation of the CSDL metadata file in your Entity Framework connection string. The CSDL describes the entity model. At present your entity model doesn't know about the GetCustomerList sproc. It hasn't been mapped yet.

NorthwindModel.Store is giving you a graphical representation of the SSDL metadata file in your Entity Framework connection string. The SSDL describes the database model.

(The MSL metadata file in your Entity Framework connection string describes the mapping between the CSDL and the SSDL).

4. So you need to map the GetCustomerList sproc in the data store to your entity model. The Entity Framework maps sprocs as Functions that you can invoke through an instance of your entity model's ObjectContext object.

In the Model Browser, open the NorthwindModel.Store node, then the Stored Procedure node. Right click on the GetCustomerList sproc and select Create Function Import. For Return type, select Customer.

5. If you now expand the EntityContainer: NorthwindEntities node under the NorthwindModel node, you will see that a Function Import has been added to your Entity Model. The following code has been added to your Entity Data Model designer.cs file:

Code:
public global::System.Data.Objects.ObjectResult<Customer> GetCustomerList()
{
   return base.ExecuteFunction<Customer>("GetCustomerList");
}
6. Your stored procedure is now mapped to your Entity Model, and you can use it as follows:
Code:
 using (NorthwindEntities db = new NorthwindEntities())
{
   foreach (Customer c in db.GetCustomerList())
   {
      Console.WriteLine(c.CompanyName);
   }
}
Of course, this whole process could have been accomplished more simply using LINQ to Entities. The following yields the same result:

Code:
using (NorthwindEntities db = new NorthwindEntities())
{
   Customer[] customers =
      (from c in db.CustomerSet
      orderby c.CompanyName
      select c).ToArray();
 
      foreach (Customer c in customers)
      {
         Console.WriteLine(c.CompanyName);
      }
}
It seems to make sense to me to limit stored procedure use in Entity Models to insert, update, and delete operations, and simply use LINQ To Entities for select operations.

Anyway, thanks for letting me review this stuff.

Bob
 
Old January 26th, 2009, 11:16 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,093
Thanks: 1
Thanked 12 Times in 11 Posts
Default

Just to clarify one point: While I referred to the SSDL/CSDL/MSL metadata as 'files', that isn't quite accurate. They are actually seperate XML elements of the .edmx file. Here is the basic structure of an .edmx file:

Code:
<edmx:Edmx>
<!-- EF Runtime content -->
<edmx:Runtime>
  <!-- SSDL content -->
  <edmx:StorageModels></edmx:StorageModels>
  <!-- CSDL content -->
  <edmx:ConceptualModels></edmx:ConceptualModels>
  <!-- C-S mapping content -->
  <edmx:Mappings></edmx:Mappings>
</edmx:Runtime>
</edmx:Edmx>
You can view your .edmx file's metadata by right clicking it, selecting Open With, and choosing XML Editor.

Here is the stored procedures SSDL (data model) content:

Code:
<Function   Name="GetCustomerList"Aggregate="false"BuiltIn="false"
            NiladicFunction="false"IsComposable="false"
            ParameterTypeSemantics="AllowImplicitConversion"Schema="dbo" />
And here is its CSDL (entity model) content after is has been imported into the entity model:

Code:
<FunctionImport Name="GetCustomerList"
                       EntitySet="CustomerSet"
                       ReturnType="Collection(NorthwindModel.Customer)" />
And finally its MSL (data model/entity model mapping) content:
Code:
<FunctionImportMapping  FunctionImportName="GetCustomerList"
                                    FunctionName="NorthwindModel.Store.GetCustomerList" />
 
Old January 27th, 2009, 01:10 AM
Registered User
Points: 38, Level: 1
Points: 38, Level: 1 Points: 38, Level: 1 Points: 38, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Bob its working fine,

I do have one more doubt regarding this,

I have Used Products and Categories Table from Northwind Database

First I created the Proc using simple Join

Create Proc GetProCategory
as
Begin
select
P.ProductName
,P.QuantityPerUnit
,P.UnitPrice
,C.CategoryName
,C.Description
from Products P
left join categories C on P.CategoryID=C.CategoryID
End

and did the Same as u have mentioned, while Creating Function Import(Mapping the Stored Procedure) for the procedure GetProCategory It asks for the return type, in that i have mentioned Categories Table as the return type.

But while Using the GetProCategory Proc i am not able the view the column from the Products tables.

code which i tried

NorthwindEntities ne = new NorthwindEntities();

foreach (Categories C in ne.GetProCategory())
{
Console.WriteLine(C.Description);
}

Hope u would have understood the Query

Please Share ur thoughts regarding this aspects
 
Old January 27th, 2009, 09:14 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,093
Thanks: 1
Thanked 12 Times in 11 Posts
Default

I'll tell you how you can make that particular sproc work, but you're not going to like the answer. There is a reason why the Entity Framework documentation doesn't describe how to build sprocs that return data. That's what LINQ To Entities and Entity SQL are for. Future bits of the Entity Framework, however, will certainly provide better support for stored procedures.

To get your sproc to work you need:

Code:
using (NorthwindEntities db = new NorthwindEntities())
{
   foreach (GetProCategoryResult c in db.GetProCategory())
   {
      Console.WriteLine(c.Description);
   }
}
But wait, GetProCategoryResult doesn't exist in your entity model. Unfortunately, you'll need to create it yourself, and that means manually editing XML (yuk).

Your sproc doesn't return either a Product entity or a Category entity. That is to say, the Entity Framework runtime doesn't return a DataReader that maps (property for property) to either a Product or a Category entity when it executes your sproc. It returns a result set that your entity model has no conception of.

Here are the necessary modifications to the SSDL,CSDL, and MSL elements of your .edmx file some, but not all of which, can be created using the designer. I'm including just the modifications, not the whole .edmx file.

Code:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="NorthwindModel.Store" 
Alias="Self" Provider="System.Data.SqlClient"
ProviderManifestToken="2008" xmlns:store=http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator 
xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
        <EntityContainer Name="NorthwindModelStoreContainer">
          <EntitySet Name="GetProCategoryResultSet" EntityType="NorthwindModel.Store.GetProCategoryResult" />
        </EntityContainer>
        <EntityType Name="GetProCategoryResult" >
          <Key>
            <PropertyRef Name="ProductName" />
          </Key>
          <Property Name="ProductName" Type="nvarchar" Nullable="false" MaxLength="40"/>
          <Property Name="QuantityPerUnit" Type="nvarchar" Nullable="true" MaxLength="20"/>
          <Property Name="UnitPrice" Type="money" Nullable="true" />
          <Property Name="CategoryName" Type="nvarchar" Nullable="true" MaxLength="15"/>
          <Property Name="Description" Type="ntext" Nullable="true" />
        </EntityType>
        <Function Name="GetProCategory" Aggregate="false" BuiltIn="false" 
NiladicFunction="false" IsComposable="false" 
ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" />
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="NorthwindModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
        <EntityContainer Name="NorthwindEntities">
          <FunctionImport Name="GetProCategory" EntitySet="GetProCategoryResultSet" 
ReturnType="Collection(NorthwindModel.GetProCategoryResult)" />
          <EntitySet Name="GetProCategoryResultSet" EntityType="NorthwindModel.GetProCategoryResult" />
        </EntityContainer>
        <EntityType Name="GetProCategoryResult" >
          <Key>
            <PropertyRef Name="ProductName" />
          </Key>
          <Property Name="ProductName" Type="String" Nullable="false" />
          <Property Name="QuantityPerUnit" Type="String" Nullable="true" />
          <Property Name="UnitPrice" Type="Decimal" Nullable="true" />
          <Property Name="CategoryName" Type="String" Nullable="true" />
          <Property Name="Description" Type="String" Nullable="true" />
        </EntityType>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
        <EntityContainerMapping StorageEntityContainer="NorthwindModelStoreContainer" CdmEntityContainer="NorthwindEntities">
          <FunctionImportMapping FunctionImportName="GetProCategory" FunctionName="NorthwindModel.Store.GetProCategory" />
          <EntitySetMapping Name="GetProCategoryResultSet" >
            <EntityTypeMapping TypeName="IsTypeOf(NorthwindModel.GetProCategoryResult)" >
              <MappingFragment StoreEntitySet="GetProCategoryResultSet" >
                <ScalarProperty Name="ProductName" ColumnName="ProductName" />
                <ScalarProperty Name="QuantityPerUnit" ColumnName="QuantityPerUnit" />
                <ScalarProperty Name="UnitPrice" ColumnName="UnitPrice" />
                <ScalarProperty Name="CategoryName" ColumnName="CategoryName" />
                <ScalarProperty Name="Description" ColumnName="Description" />
              </MappingFragment>
            </EntityTypeMapping>
          </EntitySetMapping>
        </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
There, your entity model now contains the appropriate:

1. Entity, EntitySet and FunctionImport in the entity model,

2. A matching Entity and Entity Set in the storage model,

3. And a mapping of the FunctionImport of the conceptual model to the Function in the storage model along with the necessary entity set mapping.

(I really hate XML)

Are you starting to see the advantages of LINQ to Entities yet?

Anyway, now:

Code:
using (NorthwindEntities db = new NorthwindEntities())
{
   foreach (GetProCategoryResult c in db.GetProCategory())
   {
      Console.WriteLine(c.Description);
   }
}
will work.

Bob
 
Old January 27th, 2009, 11:10 PM
Friend of Wrox
 
Join Date: Jun 2003
Posts: 1,093
Thanks: 1
Thanked 12 Times in 11 Posts
Default

Another way to think of whats going on is that since your sproc only projects fragments of the Product and Category entities, it no longer returns either of those enties, but rather System.Data.Objects.MaterializedDataRecord(s). Here's one way to get the same result set your sproc returns using Entity SQL:

Code:
 
using System;
using System.Linq;
using System.Data;
using System.Data.Common;
using System.Data.Objects;

 
 
 

private static void Test()
        {
            using (ObjectContext oc = new ObjectContext("Name=NorthwindEntities"))
            {
                try
                {
                   string eSQL = "SELECT P.ProductName, P.QuantityPerUnit, P.UnitPrice, " + 
                                        "C.CategoryName, C.Description " +
                                 "FROM NorthwindEntities.ProductSet as P " +
                                 "JOIN NorthwindEntities.FK_Products_Categories as PC ON Key(PC.Products) = ROW(P.ProductID) " +
                                 "JOIN NorthwindEntities.CategorySet as C ON Key(PC.Categories) = ROW(C.CategoryID)";
                    foreach (DbDataRecord rec in oc.CreateQuery<DbDataRecord>(eSQL, new ObjectParameter[] { })) 
                    {
                        int DescriptionOrdinal = rec.GetOrdinal("Description");
                        object DescriptionValue = rec.IsDBNull(DescriptionOrdinal) ? null : rec.GetValue(DescriptionOrdinal);
                        Console.WriteLine(DescriptionValue);
                    }
                }
                catch (EntitySqlException ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
 
Old January 30th, 2009, 10:30 AM
jminatel's Avatar
Wrox Staff
Points: 18,059, Level: 58
Points: 18,059, Level: 58 Points: 18,059, Level: 58 Points: 18,059, Level: 58
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: May 2003
Posts: 1,906
Thanks: 62
Thanked 139 Times in 101 Posts
Default

arivarasuk: You should take a look at Professional ADO.NET 3.5 with LINQ and the Entity Framework by Roger Jennings. The detailed table of contents will show you what's in the 7 Entity Framework chapters.
__________________
Jim Minatel
Associate Publisher, WROX - A Wiley Brand
Did someone here help you? Click on their post!









Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.