DCSIMG
July 2010 - Posts - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2013 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

July 2010 - Posts

Mixing Table Per Hierarchy and Entity Splitting

Mixing Table Per Hierarchy and Entity Splitting

Yesterday I published an article on the CodeProjectMixing Table Per Hierarchy and Entity Splitting
site about Table Per Hierarchy (TPH) in Entity Framework.
I got a very good question about “How would the EF handle this
with a true association table?” – which means removing the two
dates from the Person table and creating an association table instead
that will hold only one date field. This post will try to answer the
question.

The Database Diagram

In order to answer the question I first created the appropriate database.
The figure below shows its diagram:
Database Diagram

We have a person table which holds the first and last name of the person and also its type.
This table has an associated table with a one to one mapping which holds the person date (which can be enrollment date for student and hire date for professor).

Creating the Model

When you create the EDM you will first get the following model:
FirstEntityDesignerDiagram 
In order to create the inheritance tree (by imposing TPH) and using Entity Splitting to connect the PersonDateInfo into the created entities follow these steps:

Step 1
Remove the PersonDateInfo entity by deleting it.
After that, add the entities of Student and Professor to the model which inherit from Person:
 SecondEntityDesignerDiagram

Step 2
Remove the PersonType from Person, map Person also to the PersonDateInfo table and make Person abstract:
Person Mapping  
AbstractPerson 

Step 3
Create a new property on Student – EnrollementDate with DateTime type and a new property on Professor – HireDate which is also a DateTime. Map the entities to Person table and also to PersonDateInfo.
Create conditional mapping on PersonType for both entities (PersonType 1 is professor and PersonType 2 is student). Also create a conditional mapping on the DateType for both entities (DateType 1 for HireDate and dateType 2 for EnrollementDate).
After all the changes the mapping should be:
Professor Mapping
Student Mapping 
The model itself will look like:
FinishedEntityDesignerDiagram 

Step 4
When you compile the model you’ll get error 3024: Must specify mapping for all key properties.
This error rises because the mapping for the PersonDateInfo table doesn’t include mapping for the PersonID for the inheriting entities.
In order to fix this error open the model in Xml editor and add the mapping of the PersonID manually.
The following Xml is the model after the fix up:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
  <!-- EF Runtime content -->
  <edmx:Runtime>
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="SchoolModel.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/2009/02/edm/ssdl">
        <EntityContainer Name="SchoolModelStoreContainer">
          <EntitySet Name="Person" EntityType="SchoolModel.Store.Person" store:Type="Tables" Schema="dbo" />
          <EntitySet Name="PersonDateInfo" EntityType="SchoolModel.Store.PersonDateInfo" store:Type="Tables" Schema="dbo" />
          <AssociationSet Name="FK_PersonDateInfo_Person" Association="SchoolModel.Store.FK_PersonDateInfo_Person">
            <End Role="Person" EntitySet="Person" />
            <End Role="PersonDateInfo" EntitySet="PersonDateInfo" />
          </AssociationSet>
        </EntityContainer>
        <EntityType Name="Person">
          <Key>
            <PropertyRef Name="PersonID" />
          </Key>
          <Property Name="PersonID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
          <Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="50" />
          <Property Name="FirstName" Type="nvarchar" Nullable="false" MaxLength="10" />
          <Property Name="PersonType" Type="tinyint" Nullable="false" />
        </EntityType>
        <EntityType Name="PersonDateInfo">
          <Key>
            <PropertyRef Name="PersonID" />
          </Key>
          <Property Name="PersonID" Type="int" Nullable="false" />
          <Property Name="PersonDate" Type="datetime" />
          <Property Name="DateType" Type="tinyint" Nullable="false" />
        </EntityType>
        <Association Name="FK_PersonDateInfo_Person">
          <End Role="Person" Type="SchoolModel.Store.Person" Multiplicity="1" />
          <End Role="PersonDateInfo" Type="SchoolModel.Store.PersonDateInfo" Multiplicity="0..1" />
          <ReferentialConstraint>
            <Principal Role="Person">
              <PropertyRef Name="PersonID" />
            </Principal>
            <Dependent Role="PersonDateInfo">
              <PropertyRef Name="PersonID" />
            </Dependent>
          </ReferentialConstraint>
        </Association>
      </Schema>
    </edmx:StorageModels>
    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema Namespace="SchoolModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
        <EntityContainer Name="SchoolEntities" annotation:LazyLoadingEnabled="true">
          <EntitySet Name="People" EntityType="SchoolModel.Person" />
        </EntityContainer>
        <EntityType Name="Person" Abstract="true">
          <Key>
            <PropertyRef Name="PersonID" />
          </Key>
          <Property Name="PersonID" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
          <Property Name="LastName" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
          <Property Name="FirstName" Type="String" Nullable="false" MaxLength="10" Unicode="true" FixedLength="false" />
        </EntityType>
        <EntityType Name="Student" BaseType="SchoolModel.Person" >
          <Property Type="DateTime" Name="EnrollementDate" Nullable="false" />
        </EntityType>
        <EntityType Name="Professor" BaseType="SchoolModel.Person" >
          <Property Type="DateTime" Name="HireDate" Nullable="false" />
        </EntityType>
      </Schema>
    </edmx:ConceptualModels>
    <!-- C-S mapping content -->
    <edmx:Mappings>
      <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
        <EntityContainerMapping StorageEntityContainer="SchoolModelStoreContainer" CdmEntityContainer="SchoolEntities">
          <EntitySetMapping Name="People">
            <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Person)">
              <MappingFragment StoreEntitySet="Person">
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <ScalarProperty Name="FirstName" ColumnName="FirstName" />
                <ScalarProperty Name="LastName" ColumnName="LastName" />
              </MappingFragment>
              <MappingFragment StoreEntitySet="PersonDateInfo">
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Professor)">
              <MappingFragment StoreEntitySet="Person">
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <Condition ColumnName="PersonType" Value="1" />
              </MappingFragment>
              <MappingFragment StoreEntitySet="PersonDateInfo" >
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <ScalarProperty Name="HireDate" ColumnName="PersonDate" />
                <Condition ColumnName="DateType" Value="1" />
              </MappingFragment>
            </EntityTypeMapping>
            <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Student)">
              <MappingFragment StoreEntitySet="Person">
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <Condition ColumnName="PersonType" Value="2" />
              </MappingFragment>
              <MappingFragment StoreEntitySet="PersonDateInfo" >
                <ScalarProperty Name="PersonID" ColumnName="PersonID" />
                <ScalarProperty Name="EnrollementDate" ColumnName="PersonDate" />
                <Condition ColumnName="DateType" Value="2" />
              </MappingFragment>
            </EntityTypeMapping>
            </EntitySetMapping>
        </EntityContainerMapping>
      </Mapping>
    </edmx:Mappings>
  </edmx:Runtime>
  <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
  <Designer xmlns="http://schemas.microsoft.com/ado/2008/10/edmx">
    <Connection>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
      </DesignerInfoPropertySet>
    </Connection>
    <Options>
      <DesignerInfoPropertySet>
        <DesignerProperty Name="ValidateOnBuild" Value="true" />
        <DesignerProperty Name="EnablePluralization" Value="False" />
        <DesignerProperty Name="IncludeForeignKeysInModel" Value="True" />
      </DesignerInfoPropertySet>
    </Options>
    <!-- Diagram content (shape and connector positions) -->
    <Diagrams>
      <Diagram Name="SchoolModel">
        <EntityTypeShape EntityType="SchoolModel.Person" Width="1.5" PointX="1.25" PointY="2.875" Height="1.5956835937499996" IsExpanded="true" />
        <EntityTypeShape EntityType="SchoolModel.Student" Width="1.5" PointX="4.25" PointY="5.375" Height="1.2110807291666665" />
        <InheritanceConnector EntityType="SchoolModel.Student" >
          <ConnectorPoint PointX="2" PointY="4.47068359375" />
          <ConnectorPoint PointX="2" PointY="5" />
          <ConnectorPoint PointX="5" PointY="5" />
          <ConnectorPoint PointX="5" PointY="5.375" />
        </InheritanceConnector>
        <EntityTypeShape EntityType="SchoolModel.Professor" Width="1.5" PointX="6.5" PointY="5.375" Height="1.2110807291666665" />
        <InheritanceConnector EntityType="SchoolModel.Professor" >
          <ConnectorPoint PointX="2" PointY="4.47068359375" />
          <ConnectorPoint PointX="2" PointY="5" />
          <ConnectorPoint PointX="7.25" PointY="5" />
          <ConnectorPoint PointX="7.25" PointY="5.375" />
        </InheritanceConnector>
      </Diagram>
    </Diagrams>
  </Designer>
</edmx:Edmx>

Pay attention to the C-S mapping – the fix is located there. The code for the C-S mapping:

<EntitySetMapping Name="People">
    <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Person)">
      <MappingFragment StoreEntitySet="Person">
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
        <ScalarProperty Name="FirstName" ColumnName="FirstName" />
        <ScalarProperty Name="LastName" ColumnName="LastName" />
      </MappingFragment>
      <MappingFragment StoreEntitySet="PersonDateInfo">
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
      </MappingFragment>
    </EntityTypeMapping>
    <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Professor)">
      <MappingFragment StoreEntitySet="Person">
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
        <Condition ColumnName="PersonType" Value="1" />
      </MappingFragment>
      <MappingFragment StoreEntitySet="PersonDateInfo" >
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
        <ScalarProperty Name="HireDate" ColumnName="PersonDate" />
        <Condition ColumnName="DateType" Value="1" />
      </MappingFragment>
    </EntityTypeMapping>
    <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.Student)">
      <MappingFragment StoreEntitySet="Person">
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
        <Condition ColumnName="PersonType" Value="2" />
      </MappingFragment>
      <MappingFragment StoreEntitySet="PersonDateInfo" >
        <ScalarProperty Name="PersonID" ColumnName="PersonID" />
        <ScalarProperty Name="EnrollementDate" ColumnName="PersonDate" />
        <Condition ColumnName="DateType" Value="2" />
      </MappingFragment>
    </EntityTypeMapping>
</EntitySetMapping>

Step 5
Check the model.
The following code will query for the count of the students, professors and all people in the database:

using (var context = new SchoolEntities())
{
  var students = context.People.OfType<Student>();
  Console.WriteLine(students.ToTraceString());
  var professors = context.People.OfType<Professor>();
  Console.WriteLine(professors.ToTraceString());
  var people = context.People.Count();
  Console.WriteLine("students:{0} proffesors:{1} all:{2}", students.Count(), professors.Count(), people);
}

The ToTraceString will output the query that is going to be sent to the database.
The result of the running of this program:
Query Results

Summary

Let sum up, I showed how to impose two model customization methods in one model – TPH and Entity Splitting.
Customizing the model is a very common thing to do in order to create our needed conceptual model.
As you could see we can combine model customizations in order to achieve our need.

ASP.NET Output Cache Provider

ASP.NET Output Cache Provider

One of the newASP.NET Output Cache Provider
features that were
shipped with
ASP.NET 4
was new providers
for caching purpose.
In this post I’ll explain
one of them – the OutputCacheProvider.

OutputCacheProvider

Up until ASP.NET 4 the output cache mechanism was implemented as
in-memory caching and we couldn’t do nothing to change its behavior.
If we desired to use a distributed cache like AppFabric caching or our own
implementation we couldn’t achieve it. From ASP.NET 4 the caching is now
following the ASP.NET provider model which means that we can create
our own provider in order to use caching. If we wish to use our own output
cache all we need to do is to inherit the OutputCacheProvider class which
exists in the System.Web.Caching namespace. After we implement the relevant
interface that include the Add, Get, Remove and Set methods we can
plug our provider inside the web.config file in order to use it.

OutputCacheProvider Example

As I wrote all we need to do is to inherit the OutputCacheProvider class.
The following code sample is a naive in-memory implementation for
OutputCacheProvider:

public class InMemoryOutputCacheProvider : OutputCacheProvider
{
  #region Members
 
  private Dictionary<string, InMemoryOutputCacheItem> _cache = new Dictionary<string, InMemoryOutputCacheItem>();
  private readonly static object _syncLock = new object();
 
  #endregion
 
  #region Methods
 
  public override object Add(string key, object entry, DateTime utcExpiry)
  {
    Set(key, entry, utcExpiry);
    return entry;
  }
 
  public override object Get(string key)
  {
    InMemoryOutputCacheItem item = null;
    if (_cache.TryGetValue(key, out item))
    {
      if (item.UtcExpiry < DateTime.UtcNow)
      {
        Remove(key);
        return null;
      }
      return item.Value;
    }
    return null;
  }
 
  public override void Remove(string key)
  {
    InMemoryOutputCacheItem item = null;
    if (_cache.TryGetValue(key, out item))
    {
      _cache.Remove(key);
    }
  }
 
  public override void Set(string key, object entry, DateTime utcExpiry)
  {
    var item = new InMemoryOutputCacheItem(entry, utcExpiry);
    lock (_syncLock)
    {
      if (_cache.ContainsKey(key))
      {
        _cache[key] = item;
      }
      else
      {
        _cache.Add(key, item);
      }
    }
  }
 
  #endregion
}

In the code I implement the cache as a in-memory dictionary.
The implementation is very simple and it is based on a item
class which looks like:

public class InMemoryOutputCacheItem
{
  #region Members
 
  public DateTime UtcExpiry { get; set; }
  public object Value { get; set; }
 
  #endregion
 
  #region Ctor
 
  public InMemoryOutputCacheItem(object value, DateTime utcExpiry)
  {
    Value = value;
    UtcExpiry = utcExpiry;
  }
 
  #endregion
}

Configuring the OutputCacheProvider

In order to use the previous output cache implementation we need
to plug it into the web.config file of the application. Under
system.web element we need to add the caching element. Inside the
caching element we add an outputCache element and add the provider
that we have created. The following example show you how to do that:

<?xml version="1.0"?>
<configuration>
    <appSettings/>
    <connectionStrings/>
    <system.web>
        <compilation debug="true" targetFramework="4.0">
        </compilation>
    <caching>
      <outputCache defaultProvider="InMemory">
        <providers>
          <add name="InMemory" type="InMemoryOutputCacheProvider"/>
        </providers>
      </outputCache>
    </caching>
        <authentication mode="Windows"/>
        <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
</configuration>

Checking the Implementation

Now we are ready to go and test the implementation.
The following web page contains a label control which shows the
current date and time (which is inserted in the code behind).
As you can see I added the OutputCache page directive to the page
in order to test the provider:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="HttpModuleTestWeb.WebForm1" %>
<%@ OutputCache Duration="15" VaryByParam="*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="lblTime" runat="server" />
    </div>
    </form>
</body>
</html>

The page code behind:

public partial class WebForm1 : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    lblTime.Text = DateTime.Now.ToString();
  }
}

Summery

In ASP.NET 4 the caching is now provider based. That means that
we can plug our implementation to the cache including the
output cache. In the post I showed a simple example of how to
replace the output cache with a naive in-memory implementation.

Too Much Abstractions? Follow up

Too Much Abstractions? Follow up

I asked a question about how to know when you have too much
abstractions in your code? and do more abstractions implies better
design?
I promised to do a follow up post and give my humble opinion.
So here it goes.

As architect I’m using abstractions a lot. It allows me to hide the
implementation details and create API’s for my consumers. Also, it
lets me the ability to change the implementation at a later stage of
the project if I need to and of course it makes the code more testable. 
One other thing about abstractions is that they decouple the code
we are writing which is a good thing to do. But as always with every
good there can be bad and we can abuse the use of abstractions.

One sentence that I used when I was consulting about
architecture at a customer was “too much abstractions will kill you”.
What I meant was that since we can abstract everything we need to
get the “feeling” when it is appropriate to use this method.
In the customer code there were abstractions on top of other
abstractions which provided less details or identical interface to what
they tried to abstract. So in this situation I preferred to follow the KISS
principle and remove some of the abstractions away. Now the solution is
clearer and more readable with less unneeded abstractions.

The customer’s example shows that even though abstractions are a good
practice you should understand were to apply them. For example to
abstract your infrastructure is a very good practice. Take a look at the
Enterprise Library or Spring.NET code to see how you can leverage
abstractions. On the other hand to create an interface to a Data Transfer
Object which abstract its properties is something that I’ll prefer to avoid.
The reason is that DTOs are meant to be data holders that have no
behavior. If I abstract the properties I gain nothing since in most cases
the implementation will be a getter and a setter and nothing more.
These two examples show exactly what I meant when I wrote that you
should understand were to apply abstractions.  

In conclusion, there are times that we use too much abstractions in
our code. If an abstraction doesn't add any value you shouldn’t create it
because it will complicate your code. There is no such thing as abstractions
compass which can tell you when the abstraction is needed or not (or when
you have created too much abstractions). This is why I start with a simple
implementation and then refactor my code and create the needed
abstractions. As a last statement more abstractions don’t imply better
design.

Too Much Abstractions?

Too Much Abstractions?

Yesterday I had an architecture consulting session at a major customer.
One of the questions that were raised was how to know when you
have too much abstractions in your code?
or to make it even more interesting – do more abstractions implies
better design? 
I want to make it an open discussion and to hear what is your opinion
about this subject before I’ll post my own.

OData Session is Coming

OData Session is Coming

At last my ODataOData Session is Coming
session details were
published today.
The OData ecosystem
is a growing community
of data producers and
consumers using the
Open Data Protocol to
exchange data.
The Open Data Protocol
breaks down data silos and increases the shared value of data and its
associated business logic through the Web by enabling the exposure
of any data source as a Web-friendly data feed. The easiest way to
become an OData producer in the .Net world is by using
WCF Data Services. In the session I’ll talk about things like what is OData,
how to use WCF Data Services to expose OData feeds and how to consume
OData feeds.
If you find this subject interesting you can register the event here.

See you there.

Adding a Javascript Block Into a Form Hosted by WebBrowser Control

Adding a Javascript Block Into a Form Hosted by WebBrowser Control

Today I found myselfInjecting Javascript Into WebBrowser Control
with a need to
add a javascript
block into a WebBrowser
control in order to do some
work. This post will show you
the steps to do exactly that.

The Problem

In a project I’m consulting for there was a need to dynamically add a
javascript block into a web form that is hosted inside a WebBrowser
control. So what can we do?

The Solution

We can use the Microsoft HTML Object Library to achieve the task. 
The Microsoft HTML Object Library is a COM library that you can reference
in order to create HTML elements to use in the WebBrowser control.
You first need to reference it so go to the COM tab in Add Reference view,
search it and reference it. Now you can use the following code in order to
add your script to the head section of the HTML:

HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement script = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement domElement = (IHTMLScriptElement)script.DomElement;
domElement.text = // put your script here;
head.AppendChild(script);

 

Pay attention to replace the comment with your script implementation.

Summary

Using Microsoft HTML Object Library with the WebBrowser can help
you to achieve the insertion of javascript to a web form which is
hosted inside the control.
It also enables the creating and appending other HTML elements and can
be useful for other tasks.

OData Explorer

OData Explorer

One nice tool to use with OData is theOData Explorer
OData Explorer. The OData Explorer
is a tool that helps to explore OData feeds
in a visual way and not by exploring the
Atom/JSON responses. You can download
the tool from here. Another way to use the
tool is by going to the following link:
http://Silverlight.net/ODataExplorer.

OData Explorer Requirements

The tool is a Silverlight 4 project.
In order to use it you’ll have to answer these requirements:

  • Visual Studio 2010
  • Silverlight 4 Developer runtime
  • Silverlight 4 SDK
  • Silverlight 4 tools for Visual Studio
  • Latest Silverlight Toolkit release for Silverlight 4

or of course use it on-line in the link I provided previously.

Using the Tool

When the tool start you’ll get to the Add New OData Workspace view:
OData explorer New OData Workshop

Here you can address your feed or address public OData feeds.
After choosing the workspace you’ll get into the tool:
Data Explorer 

Now you can go over the collections (entity sets) and get their information
in grid representation (which can be edited if the service is updatable):
Grid View

or in row data (Atom/JSON):
Atom JSON View

You can type your own queries in the upper text box or you can
use the Build Query view to create a query:
OData Query Builder

Summary

The OData Explorer is very useful tool when you want to
understand and look at OData feeds without understanding the
protocol. It comes with very nice features and can be very handy
in presenting your feeds.

Repository and Unit of Work T4 Template for Entity Framework

Repository and Unit of Work T4 Template for Entity Framework

Two weeks ago IRepository and Unit of Work T4 Template for Entity Framework
wrote the
Revisiting the Repository
and Unit of Work Patterns
with Entity Framework

post. One thing that I
thought would be nice
was to have an automatic
code generation that will help me to build these patterns without sweating.
So I sat down and created a T4 Template to auto generate the same patterns
that I showed in the post.

The Code

One thing to understand is that the provided T4 Template isn’t bullet
proof and errors can occur (you can change the implementation as you
like). In order to use it copy and paste the code to a .tt file that needs
to be located in the library of your Entity Data Model file
(the T4 seeks edmx files in the current directory to auto generate the
classes). Another option is to download the T4 Template from here
So here it is:

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>
<#         
if(Errors.HasErrors)
{
    return String.Empty;
}
 
CodeGenerationTools code = new CodeGenerationTools(this){FullyQualifySystemTypes = true, CamelCaseFields = false};
MetadataLoader loader = new MetadataLoader(this);
 
string open = "<";
string close = ">";
string SourceCsdlPath = FindEDMXFileName();
ReferenceCsdlPaths = new string[] {};
string namespaceName = code.VsNamespaceSuggestion();
ItemCollection = loader.CreateEdmItemCollection(SourceCsdlPath, ReferenceCsdlPaths.ToArray());
EntityContainer container = ItemCollection.GetItems<EntityContainer>().FirstOrDefault();
#>
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
 
namespace <#=namespaceName#>
{
    public interface IRepository<T> where T : class
    {    
        #region    Methods
    
        T GetById(int id);
        IEnumerable<T> GetAll();
        IEnumerable<T> Query(Expression<Func<T, bool>> filter);        
        void Add(T entity);
        void Remove(T entity);   
        
        #endregion
    }
    
    public abstract class Repository<T> : IRepository<T>
                                  where T : class
    {
        #region Members
 
        protected IObjectSet<T> _objectSet;
 
        #endregion
 
        #region Ctor
 
        public Repository(ObjectContext context)
        {
              _objectSet = context.CreateObjectSet<T>();
        }
 
        #endregion
 
        #region IRepository<T> Members
 
        public IEnumerable<T> GetAll()
        {
              return _objectSet;
        }
 
        public abstract T GetById(int id);
 
        public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
        {
              return _objectSet.Where(filter);
        }
 
        public void Add(T entity)
        {
              _objectSet.AddObject(entity);
        }
 
        public void Remove(T entity)
        {
              _objectSet.DeleteObject(entity);
        }
 
        #endregion
      }
 
<#
    foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
    {        
#>
    
    public partial class <#= entity.Name #>Repository : Repository<#=open#><#=entity.Name#><#=close#>
    {
        #region Ctor
 
        public <#= entity.Name #>Repository(ObjectContext context)
               : base(context)
        {
        }
 
        #endregion
 
        #region Methods
 
        public override <#= entity.Name #> GetById(int id)   
        {
            return _objectSet.SingleOrDefault(e => e.<#= entity.KeyMembers.First().Name #> == id);
        }
 
        #endregion        
    }
<# 
    }        
#>
        
  public interface IUnitOfWork
  {
      #region    Methods
    
    <#
        foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
        {    
    #>
        IRepository<#= open #><#= set.ElementType.Name #><#= close #> <#= set.Name #> { get; }   
    <# 
        }
    #>
    void Commit();
    
    #endregion
  }
 
  public partial class UnitOfWork : IUnitOfWork
  {
    #region Members
 
    private readonly ObjectContext _context;
    <#
        foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
        {    
    #>
    private <#= set.ElementType.Name #>Repository _<#= set.Name.ToLower() #>;
    <# 
        }
    #>    
    #endregion
 
    #region Ctor
 
    public UnitOfWork(ObjectContext context)
    {
      if (context == null)
      {
        throw new ArgumentNullException("context wasn't supplied");
      }
 
      _context = context;
    }
 
    #endregion
 
    #region IUnitOfWork Members
 
    <#
        foreach (EntitySet set in container.BaseEntitySets.OfType<EntitySet>())
        {    
    #>
    public IRepository<#= open #><#= set.ElementType.Name #><#= close #> <#= set.Name #>
    {
        get
        {
            if (_<#= set.Name.ToLower() #> == null)
            {
                _<#= set.Name.ToLower() #> = new <#= set.ElementType.Name #>Repository(_context);
            }
            return _<#= set.Name.ToLower() #>;
        }
    }
    <# 
        }
    #>    
    
    public void Commit()
    {
      _context.SaveChanges();
    }
 
    #endregion
  }
}
<#+
public string SourceCsdlPath{ get; set; }
public EdmItemCollection ItemCollection{ get; set; }
public IEnumerable<string> ReferenceCsdlPaths{ get; set; }
 
string FindEDMXFileName()
{            
    string[] entityFrameworkFiles = Directory.GetFiles(Host.ResolvePath(string.Empty), "*.edmx");
    if(entityFrameworkFiles.Length > 0)
    {
        return entityFrameworkFiles[0];
    }
    
    return string.Empty;
}
#>

 

and this is the generated code that I get after running the T4 Template
on my testing edmx file:

 
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
 
namespace ConsoleApplication1
{
    public interface IRepository<T> where T : class
    {    
        #region    Methods
    
        T GetById(int id);
        IEnumerable<T> GetAll();
        IEnumerable<T> Query(Expression<Func<T, bool>> filter);        
        void Add(T entity);
        void Remove(T entity);   
        
        #endregion
    }
    
    public abstract class Repository<T> : IRepository<T>
                                  where T : class
    {
        #region Members
 
        protected IObjectSet<T> _objectSet;
 
        #endregion
 
        #region Ctor
 
        public Repository(ObjectContext context)
        {
              _objectSet = context.CreateObjectSet<T>();
        }
 
        #endregion
 
        #region IRepository<T> Members
 
        public IEnumerable<T> GetAll()
        {
              return _objectSet;
        }
 
        public abstract T GetById(int id);
 
        public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
        {
              return _objectSet.Where(filter);
        }
 
        public void Add(T entity)
        {
              _objectSet.AddObject(entity);
        }
 
        public void Remove(T entity)
        {
              _objectSet.DeleteObject(entity);
        }
 
        #endregion
      }
 
    
    public partial class CourseRepository : Repository<Course>
    {
        #region Ctor
 
        public CourseRepository(ObjectContext context)
               : base(context)
        {
        }
 
        #endregion
 
        #region Methods
 
        public override Course GetById(int id)   
        {
            return _objectSet.SingleOrDefault(e => e.CourseID == id);
        }
 
        #endregion        
    }
    
    public partial class DepartmentRepository : Repository<Department>
    {
        #region Ctor
 
        public DepartmentRepository(ObjectContext context)
               : base(context)
        {
        }
 
        #endregion
 
        #region Methods
 
        public override Department GetById(int id)   
        {
            return _objectSet.SingleOrDefault(e => e.DepartmentID == id);
        }
 
        #endregion        
    }
    
    public partial class EnrollmentRepository : Repository<Enrollment>
    {
        #region Ctor
 
        public EnrollmentRepository(ObjectContext context)
               : base(context)
        {
        }
 
        #endregion
 
        #region Methods
 
        public override Enrollment GetById(int id)   
        {
            return _objectSet.SingleOrDefault(e => e.EnrollmentID == id);
        }
 
        #endregion        
    }
    
    public partial class PersonRepository : Repository<Person>
    {
        #region Ctor
 
        public PersonRepository(ObjectContext context)
               : base(context)
        {
        }
 
        #endregion
 
        #region Methods
 
        public override Person GetById(int id)   
        {
            return _objectSet.SingleOrDefault(e => e.PersonID == id);
        }
 
        #endregion        
    }
        
  public interface IUnitOfWork
  {
      #region    Methods
    
            IRepository<Course> Courses { get; }   
            IRepository<Department> Departments { get; }   
            IRepository<Enrollment> Enrollments { get; }   
            IRepository<Person> People { get; }   
        void Commit();
    
    #endregion
  }
 
  public partial class UnitOfWork
  {
    #region Members
 
    private readonly ObjectContext _context;
        private CourseRepository _courses;
        private DepartmentRepository _departments;
        private EnrollmentRepository _enrollments;
        private PersonRepository _people;
        
    #endregion
 
    #region Ctor
 
    public UnitOfWork(ObjectContext context)
    {
      if (context == null)
      {
        throw new ArgumentNullException("context wasn't supplied");
      }
 
      _context = context;
    }
 
    #endregion
 
    #region IUnitOfWork Members
 
        public IRepository<Course> Courses
    {
        get
        {
            if (_courses == null)
            {
                _courses = new CourseRepository(_context);
            }
            return _courses;
        }
    }
        public IRepository<Department> Departments
    {
        get
        {
            if (_departments == null)
            {
                _departments = new DepartmentRepository(_context);
            }
            return _departments;
        }
    }
        public IRepository<Enrollment> Enrollments
    {
        get
        {
            if (_enrollments == null)
            {
                _enrollments = new EnrollmentRepository(_context);
            }
            return _enrollments;
        }
    }
        public IRepository<Person> People
    {
        get
        {
            if (_people == null)
            {
                _people = new PersonRepository(_context);
            }
            return _people;
        }
    }
        
    
    public void Commit()
    {
      _context.SaveChanges();
    }
 
    #endregion
  }
}

Enjoy!

Loading WCF Data Services Ajax Script Library

Loading WCF Data Services Ajax Script Library

Since I’ve given sessions Loading WCF Data Services Scripts without Sys.require
about WCF Data Services in 
the past (when they were
called ADO.NET Data Services)
I wanted to reuse some of the Ajax
examples I showed for my coming OData 
session. One of the things that have
been changed lately were the scripts to use
when you want to make Ajax calls to your Data Service.
So I downloaded the new scripts and saw that the names
of the objects to use have been changed a little but their functionality
remained the same. Moreover we have a new feature which helps
to figure what to load and how. In this post I’ll explain how to load
the WCF Data Services scripts automatically or manually.

The New Sheriff – Script Loader

One thing to understand about the new Ajax script libraries is
that the libraries ware split into many files in order to enable the
loading of the relevant libraries that you need whenever you need them.
Also, there is a new Script Loader object which help you to load the scripts
and their dependencies automatically. So I went to the documentation
to understand how to use the new OpenDataServiceProxy object (in the past
it was called DataServiceProxy). In order to use it you need to reference the
start.debug.js (or start.js in production):

<script type="text/javascript" src="/Content/Scripts/start.debug.js"></script> 

(where /Content/Scripts is the location of all the Ajax script library files)

Also, you need to use the following statement in order to load the
relevant scripts from your server:

Sys.require([Sys.components.dataContext, Sys.components.openDataContext]);

The Sys.require statement is used to configure the Script Loader to load
the libraries of the data context and the open data context which
include all the functionality to consume WCF Data Services from Javascript.
The Script Loader will check if the libraries exists in the server in the same
directory that start.debug.js exists and then load all the components for us.
It can cause some problems if when you use relative paths so pay attention
to that. Also, using the ScriptManager we can enable a search in Microsoft
Content Delivery Network (CDN) instead of loading the files from our server.
A master page that include an OpenDataServiceProxy object can look like:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="AjaxClient.master.cs"
    Inherits="DataServiceAjaxClient.Master.AjaxClient" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>    
    <script src="/Content/Scripts/Start.debug.js" type="text/javascript"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <script type="text/javascript">
            var proxy;
            Sys.require([Sys.components.dataContext, Sys.components.openDataContext]);
            Sys.onReady(function () {
                proxy = new Sys.Data.OpenDataServiceProxy("/Services/SchoolService.svc");
            });
        </script>
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>

Pay attention to the Sys.onReady function which will be called after all the
scripts were loaded.

How to Load the Scripts Manually

In order to manually load the relevant Javascript files we first have to
figure the script files dependencies. The dependencies of files are shown
here:
Microsoft Ajax Library Relationships 
So you can use the ScriptManager to load the scripts like in the
following example (the order of the ScriptReferences is very important!):

<asp:ScriptManager ID="ScriptManager1" runat="server" AjaxFrameworkMode="Explicit">
    <Scripts>
        <asp:ScriptReference Path="~/Content/Scripts/Start.debug.js" />
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxCore.debug.js" />
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxComponentModel.debug.js" />
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxSerialization.debug.js" />            
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxNetwork.debug.js" />
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxWebServices.debug.js" />                        
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxDataContext.debug.js" />
        <asp:ScriptReference Path="~/Content/Scripts/MicrosoftAjaxOpenData.debug.js" />
    </Scripts>
</asp:ScriptManager>

 

Pay attention for the AjaxFrameworkMode attribute that is set to Explicit.
With this attribute you control which are the relevant scripts to load and the
ScriptManager only load the MicrosoftAjax.js file.

Summary

In order to use the new Ajax library you have the new Script Loader to
help you with loading the relevant scripts. If you don’t want to use the
Script Loader you should understand the dependencies of the script
libraries files and to load them according to these dependencies.

Calling a WCF Data Service From jQuery

Calling a WCF Data Service From jQuery

I’m working on a lecture Calling a WCF Data Service from jQuery
about OData which I’ll
will present next month
(stay tuned for more
details in the near future).
One of the things that
I want to show is how easy
and simple it is to consume a WCF Data Service (OData feed)
with the jQuery library. In the post I’ll show you exactly how
to do that.

jQuery’s getJSON Method

When you want to load JSON data from the server using a GET HTTP
request in jQuery you will probably use the getJSON method. That
method gets as input the server URL, a map of key-value pairs which
holds parameters to the server and a callback function to use when
the response arrives back to the client and returns the server response
in JSON format.
This method is the best candidate for consuming WCF Data Services
endpoints. If I want to use the getJSON method I’ll do something
like the example provided in the getJSON documentation:

$.getJSON('ajax/test.json', function(data) {
  $('.result').html('<p>' + data.foo + '</p>'
    + '<p>' + data.baz[1] + '</p>');
});

How to Consume WCF Data Service with jQuery getJSON Method

When we understand that WCF Data Service is just an HTTP
endpoint which returns JSON answer if addressed with
JSON request the road is very clear. If I want to consume the
service all I need to do is to create the relevant URI with the
WCF Data Service URI conventions and that is it.
The following code is an example for that:

$.getJSON("/Services/SchoolService.svc/Courses", null,
    function (data) {
        var sb = new Sys.StringBuilder();
        sb.append("<div>");                                
        $.each(data.d, function (i, item) {
            CreateDivForOneCourse(sb, item)
        });
        sb.append("</div>");
        $('#divResults').html(sb.toString());
    });

What this code is doing is going to a WCF Data Service endpoint 
that is called SchoolService.svc and retrieve the courses entity set
it holds. I don’t pass any parameters to the request so the key-value
pair is null. In the callback function I create a StringBuilder object and
append to it the response by iterating the data and creating a div
for every course. In the end I put the result as html in a div which has
an id of divResults.

The All Example Page

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ConsumeDataServicejQuery.aspx.cs"
    Inherits="DataServiceAjaxClient.ConsumeDataService.ConsumeDataServicejQuery" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="../Content/Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script src="../Content/Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script>
    <script type="text/javascript">                
        var ajaxRequest;
 
        $(document).ready(function () {                        
            $('#btnShowCourses').click(function () {
                GetCoursesData();
            });
        });
 
        function GetCoursesData() {
            if (ajaxRequest != null) {
                ajaxRequest.abort();
            }
            ajaxRequest = $.getJSON("/Services/SchoolService.svc/Courses", null,
            function (data) {
                var sb = new Sys.StringBuilder();
                sb.append("<div>");                                
                $.each(data.d, function (i, item) {
                    CreateDivForOneCourse(sb, item)
                });
                sb.append("</div>");
                $('#divResults').html(sb.toString());
            });
        }
 
        function CreateDivForOneCourse(stringBuilder, item) {
            stringBuilder.append("<div><span>");
            stringBuilder.append(item.CourseID);
            stringBuilder.append("</span>&nbsp;<span>");
            stringBuilder.append(item.Title);
            stringBuilder.append("</span></div>");
        }              
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <input type="button" id="btnShowCourses" value="Show Courses" /><br />
        <div id="divResults" />
    </div>
    </form>
</body>
</html>

After running this example the result looks like:
getJSON result

Summary

Consuming WCF Data Services with jQuery is very easy task.
By using the getJSON method we create the HTTP GET request
to the service and get the returning data in JSON format to
our disposal.