Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Entity Framework - Tooling. EdmGen.exe - Generating SSDL, CSDL, MSL from Northwind.

Blogs

Mike Taulty's Blog

Elsewhere

As a "Hello World" thing to do, I went ahead and built a new console application in Visual Studio 2008 and then added references to the Entity Framework (System.Data.Entity.dll from the GAC).

I then went off to build myself a model, I didn't want to type one in :-) so I first looked at the edmgen.exe tool for creating one for me.

Remembering that;

  • SSDL - Store Schema Definition Language (i.e. what the DB looks like)
  • CSDL - Conceptual Schema Definition Language (i.e. what your conceptual model looks like)
  • MSL - Mapping Schema Language (how to turn SSDL into CSDL and back again)

This is a bit of a "Swiss-Army-Knife" in that it has a lot of command line switches to it. The most significant seeming to be;

  • /mode
    • EntityClassGeneration - I've got CSDL and I want .NET types please.
    • FromSsdlGeneration - I've got my SSDL and I want CSDL, MSL and .NET Types please.
    • FullGeneration - I've got a DB and I want SSDL, CSDL, MSL and .NET Types please.
  • /provider
    • Which provider are we using to talk to the store? (e.g. System.Data.SqlClient)
  • /connectionString
    • How to connect to the store.
  • /incsdl
    • The name of the CSDL file to read from (if any)
  • /refcsdl
    • CSDL files that the main CSDL file references (this I think will be big in that you can build bits of CSDL and then refer to them from elsewhere like you do with C++ header files or XSD's).
  • /outmsl, /outcsdl, /outobjectlayer
    • Output files for various artifacts - looks like you can either set these explicitly or you can use the /project switch to short-cut that process.
  • /language
    • The usual suspects - CSharp, VB

I go ahead and run the generation tools against my Northwind database something like;

edmgen.exe /provider:System.Data.SqlClient /connectingString="Server=.;database=northwind;integrated security=sspi" /mode:FullGeneration /project:Northwind

The tool whirs for a while and out pop 3 files that I'm interested in - my Northwind.ssdl, Northwind.csdl, Northwind.msl files. Being the curious sort, I pull these apart a little.

The Northwind.SSDL File

The store model that the tool has pulled from Northwind starts with;

<Schema Namespace="Northwind.Store" 
        Alias="Self" 
        xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">

and then we have within that Schema element;

<EntityContainer Name="dbo">

  <EntitySet....>

  <EntitySet...>

  <AssociationSet...>

  <AssociationSet...>

</EntityContainer>

<EntityType.../>

<EntityType.../>

<Association.../>

<Association.../>

<Function.../>

<Function.../>

The way I'm getting to think about this is that the EntityType, Association and Function parts of this actually define the schema in that they define "things" that can be used within an EntityContainer - i.e. they define a shape of an entity, association or function. Then, within the EntityContainer we bring those to life by defining instances where they are used in a particular DB.

Taking a look at a particular EntityType;

  <EntityType Name="Territories">
    <Key>
      <PropertyRef Name="TerritoryID" />
    </Key>
    <Property Name="TerritoryID" Type="nvarchar" Nullable="false" MaxLength="20" />
    <Property Name="TerritoryDescription" Type="nchar" Nullable="false" MaxLength="50" />
    <Property Name="RegionID" Type="int" Nullable="false" />
  </EntityType>

And an Association;

  <Association Name="FK_Territories_Region">
    <End Role="Region" Type="Northwind.Store.Region" Multiplicity="1" />
    <End Role="Territories" Type="Northwind.Store.Territories" Multiplicity="*" />
    <ReferentialConstraint>
      <Principal Role="Region">
        <PropertyRef Name="RegionID" />
      </Principal>
      <Dependent Role="Territories">
        <PropertyRef Name="RegionID" />
      </Dependent>
    </ReferentialConstraint>
  </Association>

And a Function;

  <Function Name="GetCustomersByCountry" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
    <Parameter Name="country" Type="nvarchar(max)" Mode="in" />
  </Function>

Erm - I'll confess that at this point I got the dictionary out to look up the word Niladic.

Ok, so that all makes sense. One of the things that surprised me though is that I have some EntityTypes that I don't recognise from Northwind such as;

  <EntityType Name="Summary of Sales by Year">
    <Key>
      <PropertyRef Name="OrderID" />
    </Key>
    <Property Name="ShippedDate" Type="datetime" />
    <Property Name="OrderID" Type="int" Nullable="false" />
    <Property Name="Subtotal" Type="money" />
  </EntityType>

I wonder where these come from? Feels like some kind of view that's defined in Northwind.

Sure enough, if I go and now take a look at my EntityContainer I can see that not only do I have EntitySet definitions for all my tables but they are also there for my views. So, to provide examples.

EntitySet for a table;

 <EntitySet Name="Categories" EntityType="Northwind.Store.Categories" />

EntitySet for a view;

   <EntitySet Name="Summary of Sales by Year" EntityType="Northwind.Store.Summary of Sales by Year">
      <DefiningQuery>SELECT 
[Summary of Sales by Year].[ShippedDate] AS [ShippedDate], 
[Summary of Sales by Year].[OrderID] AS [OrderID], 
[Summary of Sales by Year].[Subtotal] AS [Subtotal]
FROM [dbo].[Summary of Sales by Year] AS [Summary of Sales by Year]</DefiningQuery>
    </EntitySet>

"Interesting" :-)

Again, within my EntityContainer I've got AssociationSets such as;

   <AssociationSet Name="FK_Territories_Region" Association="Northwind.Store.FK_Territories_Region">
      <End Role="Region" EntitySet="Region" />
      <End Role="Territories" EntitySet="Territories" />
    </AssociationSet>

So that's all easy enough to understand.

The Northwind.CSDL File

I'm not expecting anything too Earth-shattering in the Northwind.CSDL file as it's been generated for me from the store so I'm really rather hoping that it looks very much like the store otherwise things have gone wrong :-)

So, the CSDL file starts with;

<Schema 
  Namespace="Northwind" 
  Alias="Self" 
  xmlns="http://schemas.microsoft.com/ado/2006/04/edm">

and then I have an EntityContainer and a bunch of EntityType and Association definitions.

I can't determine any difference between the EntityContainer in my CSDL file and the one in my SSDL file.

I also can't determine much difference between my EntityTypes and my Association types that have been defined except, for instance, when we look at a type such as this one;

  <EntityType Name="Summary_of_Sales_by_Year">
    <Key>
      <PropertyRef Name="OrderID" />
    </Key>
    <Property Name="ShippedDate" Type="DateTime" />
    <Property Name="OrderID" Type="Int32" Nullable="false" />
    <Property Name="Subtotal" Type="Decimal" Precision="19" Scale="4" />
  </EntityType>

You'll spot that, whereas in the SSDL we had a DefininingQuery for this particular type we no longer have it here. That all seems quite natural - this is a view defined by the store (not by the conceptual model) so why should the CSDL concern itself with the fact that this is a view down at the store level? The store can provide it when asked for it and that's enough. Note that (AFAIK) it would be perfectly reasonable to define conceptual views at this level but the generation tool isn't going to do that for me as it's just done a 1:1 mapping.

The Northwind.MSL File

My MSL file starts with a Mapping;

<Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">

and then I have an EntityContainerMapping;

 <EntityContainerMapping StorageEntityContainer="dbo" CdmEntityContainer="NorthwindContext">

which contains a bunch of EntitySetMappings and AssociationSetMappings. Here's a couple of examples (naturally, it's all very "vanilla" because we let the tool do a 1:1);

    <EntitySetMapping Name="Categories" StoreEntitySet="Categories" TypeName="Northwind.Categories">
      <ScalarProperty Name="CategoryID" ColumnName="CategoryID" />
      <ScalarProperty Name="CategoryName" ColumnName="CategoryName" />
      <ScalarProperty Name="Description" ColumnName="Description" />
      <ScalarProperty Name="Picture" ColumnName="Picture" />
    </EntitySetMapping>

and for the AssociationSet;

    <AssociationSetMapping Name="EmployeeTerritories" TypeName="Northwind.EmployeeTerritories" StoreEntitySet="EmployeeTerritories">
      <EndProperty Name="Employees">
        <ScalarProperty Name="EmployeeID" ColumnName="EmployeeID" />
      </EndProperty>
      <EndProperty Name="Territories">
        <ScalarProperty Name="TerritoryID" ColumnName="TerritoryID" />
      </EndProperty>
    </AssociationSetMapping>

The Northwind.ObjectLayer.cs File

The edmgen.exe tool also emits code in the .ObjectLayer.cs file that contains a set of classes. One is derived from a base class named ObjectContext and it is called (in my case) NorthwindContext. The other classes correspond to EntitySets and are called things like Customers, Orders and so on and all derive from EntityObject. I'm not going to be using this generated code in the first instance but I'll return to it.

The Northwind.Views.cs File

Again, I'll return to this piece of generated code in a future post.

That's pretty much it - I'll follow up with another post that actually does something with these files.


Posted Mon, Aug 27 2007 3:24 PM by mtaulty

Comments

Mike Taulty's Blog wrote Entity Framework - Designer. Generating an EDMX file from Northwind in Visual Studio.
on Mon, Aug 27 2007 3:30 PM
Similar to the previous post, there's a mechanism inside of Visual Studio for generating a model without...
Mike Taulty's Blog wrote Entity Framework - Entity Provider Level. First Querying of Northwind Model.
on Mon, Aug 27 2007 3:34 PM
Having managed to get to SSDL, CSDL and MSDL files for my Northwind database it's perhaps time to do...
Mike Taulty's Blog wrote ADO.NET Entity Framework - Bringing Together A Few Previous Posts
on Wed, Aug 29 2007 5:37 PM
This is just a convenience - links to the posts that I've made so far around beta 2 of the ADO.NET Entity...
Entity Framework from Mike Taulty « vincenthome’s Software Development wrote Entity Framework from Mike Taulty &laquo; vincenthome&#8217;s Software Development
on Fri, Sep 7 2007 7:24 AM