Archive

Archive for the ‘Developing Using CodeFluent Entities’ Category

[Pet Shop Reloaded] A comparative study between CodeFluent Entities and Entity Framework

June 13, 2013 1 comment

 
Some of you may know the story about the Pet Shop application, a .NET/C# revisited version of the original Java Pet Store application made by Sun Microsystems. These two sample applications were used as a mean to show an implementation of the best practices and features of both technologies. Today, these applications begin to get dusty as they were released on November 2001 and May 2001 respectively.
 
So the SoftFluent team decided to build a reloaded version of the Pet Shop using CodeFluent Entities. To maintain the spirit of the original concept we also decided to develop a parallel version using Entity Framework.

 

Pet Shop Reloaded

Pet Shop Reloaded

 

Indeed, a recurrent question about CodeFluent Entities is how it relates to Entity Framework. SoftFluent has published a white paper giving a large set of details on how these two products differ so one can understand how CodeFluent Entities is much more than an ORM.
 
We are going to write a series of blog posts showing how some concepts and features can (or cannot) be implemented using CodeFluent Entities and Entity Framework. We may not cover all the concepts or features of the two products (as there are many), but we will treat the main features needed to successfully implement a web application.
 

We will lead this study case as objective as possible and we will love to discuss any question, remark or feedback people may give us, so don’t hesitate to comment every post.

 
You can find all the blog posts related to the Pet Shop Reloaded by SoftFluent under the tag “Pet Shop Reloaded“. Stay tuned. :)
 
 

Cheers,

The SoftFluent team.
 
 

Defining type mappers when importing a database using the Importer Wizard


You can use the Importer Wizard to import an existing data base as a CodeFluent Entities model. You can access the Importer from the Modeler or the solution explorer on your CodeFluent Entities project (right click).
 

The Importer Wizard

The Importer Wizard


 
The importer makes a mapping between the data source types and the CodeFluent Entities types. But, you may want to define your own mapping configuration for a given type.
 
To do that, go to the “advanced properties” of the Importer Wizard and select “Type Mappers” under the “Input Mapping” group and add your type mapper.
 
Type Mappers Configuration

Type Mappers Configuration


 
Add an Importer Type Mapper

Add an Importer Type Mapper


 
Let’s say I am importing a SQL Server 2012 database and I have a field of type “time” (more information about SQL Server 2012 type mapping here), well I would like to have a CLR type “TimeSpan” mapped to it. When I take a look at the imported model I can see that the mapped type is “time”, but when I generate the Business Object Model (BOM) layer I have a property of type “System.DateTime (nullable)”. This is because the SQL Server type “time” did not exist before the SQL Server 2008 version.
 
SQL Server time type

SQL Server time type


 
time to DateTime mapping

time to DateTime mapping


 
So we can define a “type mapper” for the SQL Server type “time”.
 
elapsedtime mapper

elapsedtime mapper


 

We could also have chosen “System.TimeSpan”, “timespan” or “duration” as the “Type Name”.

 
And now we have a CLR type “System.TimeSpan (nullable)” in our BOM for a SQL Server 2012 type “time”.
 

time to TimeSpan mapping

time to TimeSpan mapping


 

Remember that you can save your Importer Wizard configuration.

 
You can find more resources about the Importer Wizard here.
 
 
Regards,
 
Pablo Fernandez Duran
 
 

Creating a custom sub producer to only generate resources

May 16, 2013 6 comments

Generating a CodeFluent Entities model looks at all the producers, and produce each one of them, assuming they have been enabled. The BOM producer is the most important producer and generates classes from your entities. If we break down that producer, we realize that it produces different things, such as templates, resources, membership providers, membership roles, constants…

What if you wanted to only produce resources, and nothing else?
One reason would be that your project has a lot of entities, your model is pretty much finished, but you still need to add resources. Moreover, your project is hosted on TFS online, and you do not want to check out, and check in, all the new generated files, especially if they have not changed!

By default, TFS checks out all the modified files (by a human or a code generator). Then, you need to check them back in. Hosted online, this means that the check in process would contain almost all the files of your BOM and it could be time consuming.

In this post we will create a custom sub producer that will only generate resources, and nothing else.

1. Creating the project

First, you need to create a new class library project, add some of the CodeFluent Entities references as well as 2 classes (BuildOnlyResources.cs and Constants.cs):

class library project

2. Writing classes

The BuildOnlyResources class extends the ICodeDomSubProducer interface to plug itself into the OnCodeDomProduction event. The first thing to do is to cancel the production of everything besides Resources. To do this, we check the eventType retrieved from the parameter of the OnCodeDomProduction method, and set the cancel property to true.

At this stage, the sub producer will stop generating all files, except the resources. Meanwhile, it will also delete the existing files, which is not what we want! We want to keep the existing files, without modifying them. This part is handled when the eventType corresponds to the UnitProducing value. There, we go through each class, and pretend they have been generated. That way, they will not be deleted if they exist. The method that does this is the AddToGeneratedFiles(path) method from the baseProducer class.

The Constants class simply contains 2 constants, used int the BuildOnlyResources class.

3. Adding options

We need to add a couple of options for our sub producer. The first is a boolean option that describes whether the sub producer is enabled or not. If not enabled, it will not be used during the generation. The second option is a boolean that describes whether the resources are produced or not.

4. Compiling the solution

We can now compile the solution in release mode and obtain a dll, called SubProducerResources.dll. In order to use that sub producer in our CodeFluent Entities model, we need to add this dll to the folder where CodeFluent Entities was installed, located at C:\Program Files (x86)\SoftFluent\CodeFluent\Modeler by default.

5. Displaying the subproducer in the modeler.

The last step is to be able to display that sub producer in the modeler. CodeFluent Entities looks at a config file located in: C:\Users\{user}\AppData\Roaming\CodeFluent.Modeler.Design\Custom.config. You need to create it because it does not exist. Its content needs to look  like this:

<codeFluent.Modeler>
 <producerDescriptors>
 <producerDescriptor name="SubProducerResources" displayName="SubProducer Resources" category="My Custom Producers" typeName="SubProducerResources.BuildOnlyResources, SubProducerResources" />
 </producerDescriptors>
</codeFluent.Modeler>

6. Ready

Your sub producer is ready to be used! Open your CodeFluent Entities project, right-click on your BOM producer, and add a new sub producer. You should see your sub producer in the list:

custom sub producer

Once added, it will appear under your BOM producer:

Custom Sub Producer

Here is what you are really looking for, the code for both BuildOnlyResources and Constants classes:

using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Xml;
using CodeFluent.Model;
using CodeFluent.Model.Common.Design;
using CodeFluent.Model.Design;
using CodeFluent.Producers.CodeDom;
using CodeFluent.Runtime.Utilities;

namespace SubProducerResources
{
    [Category("Business Layer Producers")]
    [DisplayName("SubProducer Resources")]
    [Producer(Constants.CustomResourcesProducerNamespaceUri, Constants.CustomResourcesProducerNamespacePrefix)]
    public class BuildOnlyResources : ICodeDomSubProducer
    {
        private CodeDomBaseProducer _baseProducer;
        private CodeFluent.Producers.CodeDom.SubProducer _subProducer;

        [Description("Determines if sub producer is enabled.")]
        [Category("Configuration")]
        [DefaultValue(true)]
        [DisplayName("Is Enabled")]
        [ModelLevel(ModelLevel.Normal)]
        public virtual bool Enabled
        {
            get
            {
                return XmlUtilities.GetAttribute(Element, "enabled", true);
            }
            set
            {
                XmlUtilities.SetAttribute(Element, "enabled", value.ToString().ToLowerInvariant());
            }
        }

        [Description("Determines if resources are produced.")]
        [Category("Configuration")]
        [DefaultValue(true)]
        [DisplayName("Produce Resources")]
        [ModelLevel(ModelLevel.Normal)]
        public virtual bool ProduceResources
        {
            get
            {
                return XmlUtilities.GetAttribute(Element, "produceResources", true);
            }
            set
            {
                XmlUtilities.SetAttribute(Element, "produceResources", value.ToString().ToLowerInvariant());
            }
        }

        public virtual void Initialize(CodeDomBaseProducer baseProducer, CodeFluent.Producers.CodeDom.SubProducer subProducer, IDictionary context)
        {
            _baseProducer = baseProducer;
            _subProducer = subProducer;
            baseProducer.CodeDomProduction += OnCodeDomProduction;
        }

        public virtual void Produce(IDictionary context, CodeCompileUnit unit)
        {
        }

        public virtual void Terminate(IDictionary context)
        {
        }

        private void OnCodeDomProduction(object sender, CodeDomProductionEventArgs e)
        {
            if (!Enabled)
                return;

            if (e.EventType == CodeDomProductionEventType.ResourcesProducing)
            {
                if (!ProduceResources)
                {
                    e.Cancel = true;
                }
            }
            if (e.EventType == CodeDomProductionEventType.UnitsProducing)
            {
                e.Cancel = true;
                IEnumerable<CodeCompileUnit> units = (CodeCompileUnit[])e.Argument;
                foreach (CodeCompileUnit unit in units)
                {
                    FakeProduceUnit(unit);
                }
            }
            // adapt to your needs
            if (e.EventType == CodeDomProductionEventType.ConstantsProducing ||
                e.EventType == CodeDomProductionEventType.SRProducing ||
                e.EventType == CodeDomProductionEventType.BasicAuthenticationModuleProducing ||
                e.EventType == CodeDomProductionEventType.BitsServerProducing ||
                e.EventType == CodeDomProductionEventType.MembershipProviderProducing ||
                e.EventType == CodeDomProductionEventType.MembershipUserProducing ||
                e.EventType == CodeDomProductionEventType.ProfileProviderProducing ||
                e.EventType == CodeDomProductionEventType.RoleProviderProducing)
            {
                e.Cancel = true;
            }
        }

        private void FakeProduceUnit(CodeCompileUnit unit)
        {
            if (unit == null)
                throw new ArgumentNullException("unit");

            BaseType baseType = UserData.GetBaseType(unit); // get the type related to this unit, if any
            if (baseType == null)
                return;

            // check if the type was to be produced or not

            if (!_baseProducer.MustProduce(baseType, CodeFluent.Producers.CodeDom.Constants.ModelProducerNamespaceUri))
                return;

            Set set = baseType as Set;
            if (set != null)
            {
                if (!_baseProducer.MustProduce(set.ItemEntity, CodeFluent.Producers.CodeDom.Constants.ModelProducerNamespaceUri))
                    return;
            }

            // determine the final target path where the file should have gone, and pretend it's been generated
            string path = ((CodeDomProducer)_baseProducer).GetTargetPath(baseType);
            path = _baseProducer.GetProductionTargetPath(baseType, path, false, false);

            if (File.Exists(path))
            {
                _baseProducer.AddToGeneratedFiles(path);
            }
        }

        public XmlElement Element
        {
            get
            {
                if (_subProducer == null)
                    throw new CodeFluentCodeDomProducerException(GetType().FullName);

                return _subProducer.Element;
            }
            set
            {
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SubProducerResources
{
    public sealed class Constants
    {
        public const string CustomResourcesProducerNamespaceUri = "http://www.softfluent.com/codefluent/producers.customResources/2013/1";
        public const string CustomResourcesProducerNamespacePrefix = "cfcr";

        private Constants()
        {
        }
    }
}

Vincent Patry

Patch text files after code generation with CodeFluent Entities


 
CodeFluent Entities provides a large set of concepts and tools to generate code as custom as wanted. But, it may be a reason you need to modify the output produced by the CodeFluent Entities engine when there is not an option or a feature that allows you do that.
 
The Patch Producer is a producer that lets you “patch” text files using regular expressions. You can find the Patch Producer under the Utility Producers category.
 

Patch producer

Patch producer


 
Add a Patch

Add a Patch


 
Path: can be a directory path or a file path. If relative, it is based from the directory containing the project root part.
File Search Pattern: is a file filter expression. Only used if “path” is a directory.
Search Pattern: a regular expression matching groups.
Replace: a key=value pair list separated by the “Replace Separator Character”.
 

You can use the default namespace in the path attribute using the syntax {1:DefaultNameSpace}

 
 

Example 1

 
CodeFluent Entities provides a “tracking” feature.
 

Tracking User Name

Tracking User Name


 
In most of the cases the CodeFluentUser.Name is of the form “Domain\UserName” and let’s say we only want to store in the database the “UserName” without the “Domain” (ie. The CodeFluentUser.UserName).
 
In my case I have a CodeFluent Entities project with a Business Object Model (BOM) producer and a SQL Server persistence producer. The BOM generated files are stored in a class library project having as name the default namespace.
 
So, I need to search all files matching “ *.cs ” in my BOM project:
 
.cs Search Path

.cs Search Path


 
And make the replacement using the regular expression:
,\s*persistence\.Context\.User\.(?<name>Name)\s*\)
 
And replace the matched value in the group name “name” by “UserName”:
 
UserName replace

UserName replace


 
If I build my CodeFluent Entities, now I have:
 
UserName replaced

UserName replaced


 
 

Example 2

 
CodeFluent Entities adds some information on each generated file about the generation itself. For example, for SQL files:
 

Generation information

Generation information


 
Let’s say we want to add the name our company within this information, something like “CodeFluent Generated for SoftFluent […]
We add a new “Patch” producer.
 
Generation information Patch

Generation information Patch


 
As you can see, I store my SQL files in a folder named “SQL” in the same location as my BOM generated files (cf. example 1).
 
We build the CodeFluent Entities project and now we have:
 
Generation information Patched

Generation information Patched


 
Have fun.
 
Regards,
Pablo Fernandez Duran
 
 

Using the Cache Sub-Producer

April 24, 2013 Leave a comment

 
CodeFluent Entities provides an integrated cache system for the Business Object Model (BOM) layer.  The Object Model Cache (OMC) is not enabled by default. To add the cache feature to your BOM you need to first add a Cache sub producer.
 

The Cache Sub-Producer

The Cache Sub-Producer


 
If you set the “Is Default Enable” attribute to “True” the cache feature will be enabled for all the entities in your model. You can also decide to enable or not the cache feature by entity or by method.
 
Enable Cache on an Entity

Enable Cache on an Entity


 
As you can see in the image above, you can independently specify whether you want to enable the cache feature for Collections or not by changing the value of the “Is Collection Enabled” attribute.
 
If you enable the cache feature, when calling a “LoadXXX” method (ex. Load, LoadById…) on your entity will make that a cache verification is performed before trying to load the data from the data source (SQL server for example).
 
If you want to bypass the cache you can call the “NoCacheLoadXXX” method (ex. NoCacheLoad, NoCacheLoadById…). When saving or deleting an instance of an entity, the cache is cleared (for that entity) and you can clear manually the cache calling the “CacheClear” method on an entity (public static method).
 
You may considerate some points when using a Cache system:

  • Complexity will be added to your application.
  • Unexpected behaviors may appear if not using it correctly.
  • The Object Model Cache provided by default is an in-memory cache, so it cannot be shared between servers.
  • It is not interesting to use a Cache system if the cached data changes too often. It’s best to cache immutable or almost immutable data.

 
An example scenario when the Object Model Cache feature could be useful may be when storing “referential” data on a data base or data that does not change too often.
 
CodeFluent entities provides three types of Cache implementations:

  • Simple Cache Manager, based on the ASP .NET cache (that can be used outside of ASP.NET)  (CodeFluent.Runtime.Caching.SimpleCacheManager, CodeFluent.Runtime).
  • Simple Localized Cache Manager, a sub-class of the Simple Cache Manager that can manage localized keys (CodeFluent.Runtime.Caching.LocaleCacheManager, CodeFluent.Runtime)
  • Enterprise Library Cache Management, you must install the Enterprise Library in order to use it (CodeFluent.Runtime.Caching.EnterpriseLibraryCacheManager, CodeFluent.Runtime).

 
You can specify the type of cache you want to use on the “Runtime Cache Type Name” attribute (the full type name). You can use a different cache systems by scope (entity, method).
 

Runtime Cache Type Name

Runtime Cache Type Name


 

You can use a different or custom type of cache not provided by CodeFluent Entities, you only need to implement the CodeFluent.Runtime.Caching.ICacheManager interface.

 

Finally, you can disable the cache feature by configuration (only for the Simple Cache Manager and the Simple Localized Cache Manager), for a testing or development environment for example. You only need to add the following code to your app.config or web.config file:
 

<appSettings>
   <add key="CodeFluent.Runtime.Caching.SimpleCacheManager.Enabled" value="false"/>
</appSettings>

 
 

Regards,
 
Pablo Fernandez Duran
 
 

Remove the current date and time to generated files

April 22, 2013 Leave a comment

 
 
CodeFluent Entities adds some information to generated files every time a code production is run.
 
This information contains general information (for all producers) and specific information (for each producer):
 

  • The CodeFluent Entities Build version.
  • The current date and time.
  • The Runtime version.
  • The Target version.
  • The Culture.
  • The Encoding.
  • - …

 

Generation information

Generation information


 
You might want to avoid CodeFluent Entities to add some of this information to generated code.
 
For example, each time a code production is made almost all generated files will have a new “generation date” even if the generated code is the same.
 
When using a source control system you will need to checkin/commit every single file even if  only the generation date has changed. This can lead to conflicts and unnecessary merges.

 

File Diff

File Diff

 

Well, CodeFluent Entities provides an option to remove the “generation date and time” when running producers.  
This options is found in the “advanced properties tab” at the project level  (right click on the CodeFluent Entities project > Properties).
  

Set the defaultProducerProductionFlag flag to RemoveDiffs to avoid having the “date and time” on generated files.

  

Default Producer Production Flags

Default Producer Production Flags

  

Since the CodeFluent Entities build 702 (march 2013) the RemoveDiffs production flag option now also removes the Runtime Version value added to generated files.

   

Regards,

Pablo Fernandez Duran

Using the LINQ to SQL Sub-Producer

April 17, 2013 Leave a comment

 
CodeFluent Entities gives you the possibility to make your generated Business Object Model (BOM) compatible with the LINQ to SQL data access infrastructure.
 
CodeFluent Entities ships a LINQ to SQL producer, that is in fact a Sub-Producer of the Business Object Model (BOM) Producer.
 
Let’s start by setting a model to work with.
 
For this post I will create a very simple model. A “Person” entity who has zero or more “Pets” of a given kind.
 

Pet management model

Pet management model


 
I will also add Class Library project to my solution so I can store the generated code by CodeFluent Entities.
 
I will add a Persistence producer (SQL Server) and a Business Object Model Producer. I will set the Target Directory to my Class Library project for both producers.
 
Now I can add my Linq-To-Sql producer. As said before, this producer is a Sub-Producer of the BOM Producer, so I have to add it to the BOM Producer.
 
Add Sub-Producer

Add Sub-Producer


 
LINQ to SQL Sub-Producer

LINQ to SQL Sub-Producer


 
As you can see, there is no configuration required for this Sub-Producer.
 
We need to set the “Default Entity Tracking Mode” to “None” at the project level to avoid any problem with the LINQ to SQL query provider.
 
Default Entity Tracking Modes

Default Entity Tracking Modes


 
Let’s build our CodeFluent Entities project, and open a BOM class so we can see what has been generated.
 
LINQ to SQL attributes

LINQ to SQL attributes


 
We now see that our class has been decorated with LINQ to SQL attributes. We also see that the “System.Data.Linq” namespace is not defined. To fix that we need to add a reference to the “System.Data.Linq” assembly in our BOM project.
 
We have now a LINQ to SQL compliant BOM.
 
Let’s test it using LINQ to SQL.
 
For that I will add a simple Console application. Then I add a reference to my BOM project, to the CodeFluent.Runtime assembly and to the System.Data.Linq assembly. And add the right application configuration.
 
We will use the DataContext class provided by the LINQ to SQL infrastructure to manipulate data (insert, delete, update and read). And we can retrieve the connection string from the CodeFluentContext class.
 

string connectionString = CodeFluentContext.Get(PetsManagement.Constants.PetsManagementStoreName).Persistence.ConnectionString;
using (DataContext context = new DataContext(connectionString))
{
}

 
Let’s start by adding some data to our database:
 

string connectionString = CodeFluentContext.Get(PetsManagement.Constants.PetsManagementStoreName).Persistence.ConnectionString;
using (DataContext context = new DataContext(connectionString))
{

    Person bart = new Person { Name = "Bart" };
    Pet bartsDog = new Pet { Name = "Santa's Little Helper", Age = 2, Kind = PetKind.Dog };
    bartsDog.Owner = bart;
    Pet bartsCat = new Pet { Name = "Snowball II", Age = 3, Kind = PetKind.Cat };
    bartsCat.Owner = bart;//not true, is Lisa

    Person pablo = new Person { Name = "Pablo" };
    Pet pablosDog = new Pet { Name = "Shiny", Age = 17, Kind = PetKind.Dog };
    pablosDog.Owner = pablo;
    Pet pablosDog2 = new Pet { Name = "Vanilla", Age = 10, Kind = PetKind.Dog };
    pablosDog2.Owner = pablo;

    Person ferb = new Person { Name = "Ferb" };
    Pet ferbsPet = new Pet { Name = "Perry", Age = 32, Kind = PetKind.Platypus };
    ferbsPet.Owner = ferb;

    context.GetTable<Person>().InsertAllOnSubmit(new[] { bart, pablo, ferb });
    context.GetTable<Pet>().InsertAllOnSubmit(new[] { bartsDog, bartsCat, pablosDog, pablosDog2, ferbsPet });

    context.SubmitChanges();
}

 
Now let’s retrieve all the pets grouped by “Pet kind”.
 

string connectionString = CodeFluentContext.Get(PetsManagement.Constants.PetsManagementStoreName).Persistence.ConnectionString;
using (DataContext context = new DataContext(connectionString))
{
    var petsByKind = from pet in context.GetTable<Pet>()
                        group pet by pet.Kind into gr
                        select gr;

    foreach (IGrouping<PetKind, Pet> kindGroup in petsByKind)
    {
        Console.WriteLine("----" + kindGroup.Key + "----");
        foreach (Pet pet in kindGroup)
        {
            Console.WriteLine(pet.Name + " : " + pet.Owner.Name);
        }
    }
}

 
The result is:

Pets grouped by kind

Pets grouped by kind


 
Let’s now delete a cat named “Snowball II” which owners name is “Bart”.
 

string connectionString = CodeFluentContext.Get(PetsManagement.Constants.PetsManagementStoreName).Persistence.ConnectionString;
using (DataContext context = new DataContext(connectionString))
{
    Pet petToDelete = (
                        from person in context.GetTable<Person>()
                        where
                            person.Name == "Bart"
                        from pet in person.Pets
                        where
                            pet.Kind == PetKind.Cat &&
                            pet.Name == "Snowball II"
                        select pet
                        )
                        .FirstOrDefault();

    if (petToDelete != null)
    {
        context.GetTable<Pet>().DeleteOnSubmit(petToDelete);
        context.SubmitChanges();
    }

}

 
Thanks to the LINQ to SQL Sub-Producer we can use the LINQ to SQL infrastructure with our BOM, but there are several limitations and several concepts/features that can be done by CodeFluent Entities and not supported by LINQ to SQL: The CodeFluent Entities model is richer than LINQ to SQL (rules, validation, aspects, advanced relations, automatic tracking, cache, circular dependencies, multi-databases…).
  

Regards,
Pablo Fernandez Duran

Create Windows Azure Mobile Services in a few minutes thanks to CodeFluent Entities

April 5, 2013 Leave a comment

You may have heard that a lot of new features were added to Windows Azure during the last few months.

Today we will focus on Windows Azure Mobile Services. First of all, what is it?

Long story short, Windows Azure Mobile Services allows you to expose your data through JSON web services. Microsoft provides SDKs for Windows Store and Windows Phone 8 apps, pre-configured projects for iOS and Android, and JavaScript libraries for HTML.

The SDKs offer a large number of methods that provide access to your data stored in Azure.

So let us create a new CodeFluent Entities project. As an example for this article, we will use the “advertising sample” model. I will also add a class library project which will contain our SQL scripts.

We will not need more for this article since we are just going to generate the SQL Azure database with CodeFluent Entities.

First, we will add the SQL Azure Producer to our project. Regarding the configuration of the producer, we will only set the property “Produce Scripts” of the SQL Azure section to “true”.

1

Also, and this is really important, we will set the “Produce Schema” property to “true”. This property can be found by clicking on the “Advanced Properties” button as shown in the following screenshot.

2

You may wonder why this is so important. It is simply because Windows Azure Mobile Services will use the name we are going to define for our service to map it with the schema name of our database tables. So choose it carefully!

In this example, we are going to name our schema “sampleadvertising”. To do so, we have to open the properties of our entities and fill in the schema property as shown below.

3

Once we have updated the “Schema name” property of each entity we want to expose, we can build our project to produce our database.

When the project has been produced, check the database in SQL Azure to make sure we have our custom schema name on our tables.

4

Let us go back on Windows Azure to create our mobile service. According to the schema name we used in this example, we will name it “sampleadvertising” and we will associate it with the database created earlier.

5

6

Now that our service has been created, click on the “Data” tab of our service to “add a table”. Here we will add tables which names are identical to our database tables; for instance, “Campaign”.

7

8

Note: for the purpose of this article we will set the authorization for all CRUD methods to “Everyone”. Do not do the same on production especially if you work with sensitive data.

Those tables are not new database tables, they are only created to associate the tables created thanks to CodeFluent Entities with our mobile service and therefore expose our database data.

Once the table is added, we can access our data from everywhere in a standardized format.

9

From now on, we will show how to use our data from a sample Windows Store application.

First of all, we need to install the Windows Azure Mobile Services SDK which can be found at this address: https://go.microsoft.com/fwLink/?LinkID=257545&clcid=0x40C

Once the SDK is installed, let us add a new project to our solution, a blank C# Windows Store app, named “SampleAdvertising.App”.

Then add a reference to the SDK we have previously installed.

10

Let us open the file “App.xaml.cs” to register our mobile service. In our case, we will add the following code:

    <br />public static MobileServiceClient MobileService = new MobileServiceClient(&quot;https://sampleadvertising.azure-mobile.net/&quot;);     <br />

In this particular example, we will not need to register the application key since we have set the permissions to “everyone”.

Now that our service is registered, I will show you how to consume our database data.

For instance, we will query our table “Customer” to get the customer “SoftDia”. To do so, we will create an async method that will get our “Customer” table. Then we will use the “ReadAsync” method with a query filter based on our “Customer_Name” column.

Finally, we will get a JsonObject from this IJsonValue and display its content in our Visual Studio output.

Here is the code used:

    <br />GetCustomerByName(&quot;SoftDia&quot;);</p>  <p>private async void GetCustomerByName(string customerName)</p>  <p>{</p>  <p>IMobileServiceTable customerTable = App.MobileService.GetTable(&quot;Customer&quot;);</p>  <p>IJsonValue myCustomer = await customerTable.ReadAsync(&quot;$filter=(Customer_Name eq '&quot; + customerName + &quot;')&quot;);</p>  <p>JsonObject myCustomerObject = myCustomer.GetArray()[0].GetObject();</p>  <p>foreach (var item in myCustomerObject)</p>  <p>{</p>  <p>Debug.WriteLine(item.Key.ToString() + &quot;: &quot; + item.Value.Stringify());</p>  <p>}</p>  <p>}    <br />

And this is what we get from our “Customer” table

11

Cheers,

Aymeric ROLAND

Retrieve SQL Output parameters in your BOM with CodeFluent Entities

March 27, 2013 Leave a comment

 
 
Let’s say you have an existing stored procedure that uses OUTPUT parameters to retrieve some data and you want to access it in your Business Object Model (BOM) as an object method.
 
If you can modify your procedure you might want to use a more OOP (Object Oriented Programming) approach. It will be more flexible and it is what CodeFluent Entities follows.
 
But let’s suppose you don’t have the possibility to modify your stored procedure.
 
We will use an existing model to illustrate this post. We will work with the ContactManager demo project available within the CodeFluent Entities project templates in Visual Studio.
 
This is how our existing stored procedure looks like, it has 2 OUTPUT parameters.
 

CREATE PROCEDURE [dbo].[legacy_procedure]
(
@param1 [int] OUTPUT,
@param2 [nvarchar] (256) OUTPUT
)
AS
BEGIN
--some interesting code here
select @param1 = 42
select @param2 = 'answer'
END
GO

 

We create a method called “LegacyProcedure” related to the entity Contact

Add a method to an entity

Add a method to an entity

 

Name the method

Name the method


 
We need to create a “raw” method and specify the parameters for our method.
 
As we want to use an existing stored procedure we leave the body empty.

Defining our method

Defining our method


 
As we will work with an existing stored procedure we need to tell our method to use our existing stored procedure, and not to create his own persistence stored procedure.

 
In the method advanced properties at the “persistence” level we set “Persistence Name” (it must be the same name as the stored procedure).

Set the persistence method name

Set the persistence method name


 
Now we tell the persistence producer not to produce the stored procedure.
To do that we go to the “Aspect and Producer Properties” of our method and set the “Produce” value to False.

Persistence Produce Property

Persistence Produce Property


 
Finally we need to define the parameters that are used in our method.

The method parameters

The method parameters


 
The parameter names must be the same as those declared in our method (as well as the type).

Parameter names

Parameter names


 
Now we need to set the persistence parameter direction. Displaying the advanced properties, in the persistence group we set the direction to “Output”.

Parameter persistence direction

Parameter persistence direction


 
Supposing that you have a “Persistence producer” and a “Business Object Model producer” (BOM) we build the CodeFluent Entities project.
 
If you have a CodeFluent Entities version former to the Build 1.0.61214.707, then you will have a compile error while building the generated BOM project.

Output parameters are not handled

Output parameters are not handled


 
The solution would be to disable the generation of our method and code it by hand in a partial class.
 
But, since Build 1.0.61214.707 CodeFluent Entities now supports the “out” and “ref” parameters in persistence methods.
 
After installing the new version, we build the CodeFluent Entities project. If we take a look at our generated method we will see that the “out” parameters are now handled by our BOM.

Out parameters are handled

Out parameters are handled


 
 
Regards,
Pablo Fernandez Duran

Generate ASP .NET Web API Controllers using Templates

March 20, 2013 Leave a comment

 

In a precedent post we have shown how to build an ASP .NET WebAPI Controller to access the generated Business Object Model (BOM).
 
We saw how to implement manually a Web API Controller for one entity of our model.
 
Now, we are going to see how to build a Template in order to automatically generate a Web API Controller for each one of the entities in our model.
 
We are going to use the “CarRental” demo project included with CodeFluent Entities. It was the same sample project that we used when we created the Web API Controller.
 
The first thing we have to do is create our template file.

 

Templates location

Templates location

 

Our template must be prefixed by “[Template]” and have an extension of type “.tpl”.

 
Before writing our template let’s create a producer for our template.
 

Template Producer

Template Producer


 
The “Source Directory” is the location of our template folder and the “Target Directory” is where our files will be generated, in my case I have a folder called “ApiControllers” in my MVC 4 Web Application project.
 
At the bottom of our template we fix some parameters.

[%@ template
enumerable="Producer.Project.Entities"
enumerableItemName="entity"
enumerableTargetPathFunc='Path.Combine(Path.GetDirectoryName(TargetPath), entity.Name) + "Controller.cs"' %]

 
That means that we are going to iterate through all the entities in our project (Producer.Project.Entities). Inside the template we can access the current enumerated entity by the name “entity”. And the name of the generated file (for each entity) will be “[EntityName]Controller.cs”.
 
Now we can write the content of our Api Controller. Let’s start by creating only the Controller class.

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the Template Producer.
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace [%=entity.Namespace%].Web.ApiControllers
{
	using System.Collections.Generic;
	using System;
	using System.Net;
	using System.Net.Http;
	using System.Web.Http;

    public class [%=entity.Name%]Controller : ApiController
    {
    }
}

 
If we build our CodeFluent Entities project we must see our Api Controllers appear.
 

Generated API Controllers

Generated API Controllers


 
Now let’s implement the Api Controller methods. We will use almost the same implementation as we did in the post “Using ASP .NET Web API with CodeFluent Entities”.

// GET api/[%=entity.Name%]
public IEnumerable<[%=entity.Name%]> Get()
{
    return [%=entity.SetFullTypeName%].LoadAll();
}

// POST api/[%=entity.Name%]
public HttpResponseMessage Post([FromBody][%=entity.Name%] value)
{
	if(value == null || !value.Save())
	{
		return Request.CreateResponse(HttpStatusCode.BadRequest);
	}
	return Request.CreateResponse(HttpStatusCode.OK, value);
}

// PUT api/[%=entity.Name%]
public HttpResponseMessage Put([FromBody][%=entity.Name%] value)
{
	if(value == null || !value.Save())
	{
		return Request.CreateResponse(HttpStatusCode.BadRequest);
	}
	return Request.CreateResponse(HttpStatusCode.OK, value);
}

 

For the Delete and Get (for a single element) methods we need to do some work to manage the entity keys. Indeed, it is possible that some entities have multiple keys.

// DELETE api/[%=entity.Name%]/*ids
public HttpResponseMessage Delete(string ids)
{
	ids = ids.Replace('/', '|');
    [%=entity.ClrFullTypeName%] value = [%=entity.ClrFullTypeName%].LoadByEntityKey(ids);
	if(value != null && value.Delete())
	{
		return Request.CreateResponse(HttpStatusCode.NoContent);
	}
	return Request.CreateResponse(HttpStatusCode.NotFound);
}

	// GET api/[%=entity.Name%]/*ids
public [%=entity.Name%] Get(string ids)
{
	ids = ids.Replace('/', '|');
    [%=entity.ClrFullTypeName%] value = [%=entity.ClrFullTypeName%].LoadByEntityKey(ids);
	if(value == null)
	{
		throw new HttpResponseException(HttpStatusCode.NotFound);
	}
	return value;
}

 
We use a feature in MVC (and Web API) routes that allows us to handle a variable number of segments in a URL pattern.
 
So we will need to make some changes in our routing configuration. I have registered my routes for the Web API in a separate file called “WebApiConfig” (cf. Using ASP .NET Web API with CodeFluent Entities). The trick lies in the “*” before the parameter name (*ids).

config.Routes.MapHttpRoute(
                           name: "DefaultApi",
                           routeTemplate: "api/{controller}/{*ids}",
                           defaults: new { ids = RouteParameter.Optional }
                          );

 

For example, in order to retrieve a specific instance of the entity “InventoryDetail” we need three keys, so the URL to get an instance of “InventoryDetail” will be: http://server/api/InventroyDetail/1/2/3.

 
If we build our CodeFluent Entities project and take a look at the inside of a Controller we will see the complete implementation.
 
Now we only have to test our Controllers. We can use the same tests that we have done in the precedent post related to the ASP .NET Web API.

 
Regards.
 
Pablo Fernandez Duran

Follow

Get every new post delivered to your Inbox.

Join 694 other followers

%d bloggers like this: