Archive

Archive for August, 2013

[Pet Shop Reloaded] Using the generated code – Part 2

August 13, 2013 Leave a comment

In the previous article, we talked about using the code generated by CodeFluent Entities. On this one, we will first focus on the code generated by Entity Framework then we will summarize in a conclusion what is provided by the two solutions.
 

I – Use of Entity Framework generated code

In order to use the code generated by Entity Framework we will need to have some assemblies referenced in our project like “System.Data.Entity”, “EntityFramework”. Nevertheless, in our case we choose an ASP.NET MVC project and those are included out-of-the-box in the solution.

First of all, we have seen in the previous article that CodeFluent Entities generates out-of-the-box a BLOB handler for our images stored in the database. Obviously, Entity Framework doesn’t generate it for us, therefore we have to create our own BLOB handler.

To do so, we will add a new .ashx file at the root of our solution named “ImageHandler.ashx”. This file will contain the following code.

public class ImageHandler : IHttpHandler
{
  public void ProcessRequest(HttpContext context)
  {
    ModelContainer _db = new ModelContainer();
    string idStr, entityType;
    int id;

    if ((idStr = context.Request.QueryString.Get("ID")) != null && (entityType = context.Request.QueryString.Get("type")) != null && int.TryParse(idStr, out id))
    {
      if (entityType == "product")
      {
        Product product = _db.Product.Single(p => p.Id == id);
        context.Response.Clear();
        context.Response.ContentType = "image/jpg";
        context.Response.BinaryWrite(product.Image);
        context.Response.End();
      }
      else if (entityType == "item")
      {
        Item item = _db.Item.Single(i => i.Id == id);
        context.Response.Clear();
        context.Response.ContentType = "image/jpg";
        context.Response.BinaryWrite(item.Image);
        context.Response.End();
      }
    }
  }

  public bool IsReusable
  {
    get
    {
      return true;
    }
  }
}

As you can see, our class inherits from “IHttpHandler”, and based on the type it will either return the product image or the item image.

Once the handler created we will need to modify the “Web.config” file to reference our “ImageHandler” according to the following code.

<configuration>
  . . .
  <system.webServer>
    . . .
    <handlers>
      <add name="ImageHandler" verb="*" path="*.ashx" type="EF.PetShopReloaded.WebApp.ImageHandler,EF.PetShopReloaded.WebApp" />
      . . .
    </handlers>
  </system.webServer>
  . . .
</configuration>

In order for our blob handler to work we need to add a new route to be ignored in our “RouteConfig.cs” file as it is showed in the code below.

routes.IgnoreRoute("{handler}.ashx");

Our “Web.config” file is set up, our web application is able to reach our database, display images stored in, and use generated providers.

To be able to request data stored we also needed to instantiate our “ModelContainer” thanks to the following code.

public static ModelContainer _db = new ModelContainer();

As we did in the previous article with the code generated thanks to CodeFluent Entities, we will create a “CategoryController” containing an “Index” ActionResult method which will be used to retrieve products based on their category name.

public class CategoryController : Controller
{
  [HttpGet]
  public ActionResult Index(string name)
  {
    var products = EF.PetShopReloaded.WebApp.MvcApplication._db.Product.Where(c => c.Category.Name == name).ToList();

    if (products.Count != 0)
    {
      ViewBag.CategoryName = name;

      return View(products);
    }
    else if (products.Count == 0)
    {
      ViewBag.CategoryName = "No such category";

      return View(products);
    }
    else
      return RedirectToAction("Index", "Home");
  }
}

Let’s focus on the line

var products = EF.PetShopReloaded.WebApp.MvcApplication._db.Product.Where(c => c.Category.Name == name).ToList();

We used LINQ-to-Entities to retrieve all the products by name, in this example this is a very simple query and maybe we won’t have any problem when trying to debug it. However when we have more complicated queries it will be harder to debug them if there is a problem, this because Entity Framework generate SQL code on the fly, so we will need to use a profiler tool to see the actual query that is sent to the SQL server.

Obviously we can also manipulate data thanks to the code generated by Entity Framework. As we have seen in the article treating about the creation of the model of the application with CodeFluent Entities we are able to create instances to add data at generation but such a feature isn’t provided by Entity Framework and we had to create data manually from code. Therefore, we will use these data creation scripts to illustrate how to manipulate data with Entity Framework.

Regarding data creation we will take as example the “CreateCategories” class which can be find under the “Data” folder. As you can see in the code below, we are adding new categories and persisting them by calling the “SaveChanges” method.

public class CreateCategories
{
  public CreateCategories(ModelContainer _db)
  {
    _db.Category.Add(new Category() { Name = "Birds", Description = "Birds" });
    _db.Category.Add(new Category() { Name = "Backyard", Description = "Backyard" });
    _db.Category.Add(new Category() { Name = "Bugs", Description = "Bugs" });
    _db.Category.Add(new Category() { Name = "Endangered", Description = "Endangered" });
    _db.Category.Add(new Category() { Name = "Fish", Description = "Fish" });

    _db.SaveChanges();
  }
}

In order to update data, we just need to get the category we want to modify, update its properties and finally call the “SaveChanges” method to persist changes.

//Update sample
Category category = _db.Category.Single(c =&gt; c.Name == "Birds");
category.Name = "New name";

_db.SaveChanges();

For deletion, a “Delete” method is provided by CodeFluent Entities, the sample below shows how to delete an entity with Entity Framework.

//Delete sample
_db.Category.Remove(selectedCategory);

_db.SaveChanges();

Taking for example the view where we show our items, we just want to display the content of the product list we passed from our controller. Therefore, we are creating a view which have a model type of “IEnumerable<EF.PetShopReloaded.WebApp.Models.Product>”. This view also uses the layout of the web application. Since we have passed a list we need an enumerator, in this case we are using a “foreach”, to display its content. As we did in the previous article we will once again add some style to make it look nicer.

@model IEnumerable<EF.PetShopReloaded.WebApp.Models.Product>

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2 style="color: #444444;">@ViewBag.CategoryName</h2>

@foreach (var item in Model) {
    <a class="category" href="@Url.Action("Index", "Product", new { item.Category.Description, item.Name })">
        <p class="categoryTitle">@item.Name</p>
        <img id="@item.Id" src="~/ImageHandler.ashx?ID=@item.Id&type=product" style="width: 100%; height: 200px; margin:0; padding:0;"/>
        <p style="text-align:justify; width: 278px; padding: 6px; height:35px; margin: 0; font-size: 9pt;">@item.Description</p>
    </a>
}

As you can see, the “src” property of the “img” tag isn’t a simple variable. Since our images are stored in the database as BLOBs, as we said earlier we need an http handler. In this case, the url is simpler than the one showed in the previous article but the handler is also less complex and flexible.

To conclude, we can say that CodeFluent Entities provides ready-to-use code for you developers allowing you to focus on the application you are working on.

 

II – Conclusion

In this two part article we have seen how to use code generated by both CodeFluent Entities and Entity Framework. We have seen that the code generated by CodeFluent Entities is more efficient, providing us ready-to-use and platform independent code whilst letting us focus on using it inside our application.

In the next article, we will talk more about statistics (e.g. number of lines of code, performances) to conclude this blog post series about “Pet Shop Reloaded”.

 

Cheers,

The SoftFluent Team.

[Pet Shop Reloaded] Using the generated code – Part 1

August 5, 2013 Leave a comment

In this article, we will talk about using the code generated by CodeFluent Entities and Entity Framework. On the first part of this article we will focus on using the code generated by CodeFluent Entities then on an upcoming article we will see how to use the code generated by Entity Framework and the differences between the two approaches.

Use of CodeFluent Entities generated code

In order to use the code generated by CodeFluent Entities do not forget to add a reference to our class library project which contains the generated files as well as a reference to the “CodeFluent.Runtime” and the “CodeFluent.Runtime.Web”. Those DLL can be found in the installation directory of CodeFluent Entities, by default in “C:Program Files (x86)SoftFluentCodeFluentx64”.

First of all, we need to modify the “Web.config” file according to the screenshot below to add our connection string, add the generated blob handler in the “HttpHandler” section and register membership and role providers generated by CodeFluent Entities which are based on the AspNet membership and role providers.

9

In order for our blob handler to work we need to add a new route to be ignored in our “RouteConfig.cs” file as it is showed in the code below.

 routes.IgnoreRoute("{handler}.ashx");

Once our “Web.config” file is set up, our web application is able to reach our database, display images stored in, and use generated providers.

We are now able to create a controller and a view associated to this controller to show how it works.

Therefore, I will create a “CategoryController” containing an “Index” ActionResult method which will use our custom method to load products by their category name.

Once our “Web.config” file is set up, our web application is able to reach our database, display images stored in, and use generated providers.

We are now able to create a controller and a view associated to this controller to show how it works.

Therefore, I will create a “CategoryController” containing an “Index” ActionResult method which will use our custom method to load products by their category name.

[HttpGet]
public ActionResult Index(string name)
{

ProductCollection products = ProductCollection.LoadByCategoryName(name);

if (products != null && products.Count != 0){

ViewBag.CategoryName = name;

return View(products);

}

else if (products != null && products.Count == 0){

ViewBag.CategoryName = "No such category";

return View(products);

}

else

return RedirectToAction("Index", "Home");

}

As you can see in the code above, we are getting all the matching products from our database and we returning this ProductCollection to our view.

Before going further, we will take a look to what was generated inside this “ProductCollection” class focusing on the “LoadByCategoryName” method.

[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]

public static PetShopReloaded.ProductCollection LoadByCategoryName(string category)

{

PetShopReloaded.ProductCollection ret = PetShopReloaded.ProductCollection.PageLoadByCategoryName(int.MinValue, int.MaxValue, null, category);

return ret;

}

public static System.Data.IDataReader PageDataLoadByCategoryName(CodeFluent.Runtime.PageOptions pageOptions, string category)

{

if ((category == default(string)))

{

throw new System.ArgumentNullException("category");

}

CodeFluent.Runtime.CodeFluentPersistence persistence = CodeFluentContext.Get(PetShopReloaded.Constants.PetShopReloadedStoreName).Persistence;

persistence.CreateStoredProcedureCommand(null, "Product", "LoadByCategoryName");

persistence.AddParameter("@category", category);

if ((pageOptions != null))

{

System.Collections.IEnumerator enumerator = pageOptions.OrderByArguments.GetEnumerator();

bool b;

int index = 0;

for (b = enumerator.MoveNext(); b; b = enumerator.MoveNext())

{

CodeFluent.Runtime.OrderByArgument argument = ((CodeFluent.Runtime.OrderByArgument)(enumerator.Current));

persistence.AddParameter(string.Format("@_orderBy{0}", index), argument.Name);

persistence.AddParameter(string.Format("@_orderByDirection{0}", index), ((int)(argument.Direction)));

index = (index + 1);

}

}

System.Data.IDataReader reader = CodeFluentContext.Get(PetShopReloaded.Constants.PetShopReloadedStoreName).Persistence.ExecuteReader();

return reader;

}

CodeFluent Entities automatically generates “LoadBy” methods in collection classes for each entity relationship. For example, in the “ProductCollection” class we have a “LoadByCategory” method, as a Product has a relation with Category. We have also defined a “LoadByCategoryName” method to meet our specific needs. This method was generated using CFQL which is a platform independent language (https://blog.codefluententities.com/?s=cfql).

image

You can see that the code generated by CodeFluent Entities is clear and intelligible. Plus, if your business needs requires something really specific you can still extend what was generated by CodeFluent Entities since all the classes generated are partial classes. Therefore, you can focus on what matter for you and your application and not on the plumbing code.

CodeFluent Entities also generates methods to create, modify and delete data. Regarding creation or modification, a “Save” method is provided. This method will either save modifications made to an object or create this one if it doesn’t exist and it can be used as shown in the code sample below.

//Creation sample
Product product = new Product() { Name = "Demo" };
product.Save();

//Update sample
Product product = Product.Load(MyProductId);
product.Save();

For deletion, a “Delete” method is provided by CodeFluent Entities, a sample is shown below.

//Delete sample
Product product = Product.Load(MyProductId);
product.Delete();

CRUD methods are generated by default by CodeFluent Entities for all entities.

Taking for example the view where we show our items, we just want to display the content of the “ProductCollection” we passed from our controller. Therefore, we are creating a view which have a model type of “ProductCollection”. This view also uses the layout of the web application. Since we have passed a collection we need an enumerator, in this case we are using a “foreach”, to display its content. We are also adding some style to make it look nicer.

@model PetShopReloaded.ProductCollection

@{

Layout = "~/Views/Shared/_Layout.cshtml";

}

<h2 style="color: #444444;">@ViewBag.CategoryName</h2>

@foreach (var item in Model) {

<a href="@Url.Action("Index", "Product", new { item.Category.EntityDisplayName, item.Name })">

<p>@item.Name</p>

<img id="@item.Id" src='@(Request.ApplicationPath + CodeFluent.Runtime.Web.UI.BinaryLargeObjectHttpHandler.BuildUrl(null, CodeFluent.Runtime.Web.UI.WebControls.BinaryLargeObjectUrlType.Image, "PetShopReloaded.Product", "Product_Image", null, null, null, null, null, -1, -1, 0, new object[] { item.Id }))' style="width: 100%; height: 200px; margin:0; padding:0;"/>

<p style="text-align:justify; width: 278px; padding: 6px; height:35px; margin: 0; font-size: 9pt;">@item.Description</p>

</a>

}

As you can see, the “src” property of the “img” tag isn’t a simple variable. Since our images are stored in the database as BLOB’s as we said earlier we need an http handler. This BLOB handler was also generated by CodeFluent Entities.

public partial class HttpHandler : CodeFluent.Runtime.Web.UI.BinaryLargeObjectHttpHandler

{

private CodeFluent.Runtime.CodeFluentContext _context;

public override CodeFluent.Runtime.CodeFluentContext CodeFluentContext

{

get

{

if ((this._context == null))

{

if ((this.EntityClrFullTypeName == "PetShopReloaded.Item"))

{

this._context = CodeFluentContext.Get(PetShopReloaded.Constants.PetShopReloadedStoreName);

return this._context;

}

if ((this.EntityClrFullTypeName == "PetShopReloaded.Product"))

{

this._context = CodeFluentContext.Get(PetShopReloaded.Constants.PetShopReloadedStoreName);

return this._context;

}

this._context = CodeFluentContext.Get(PetShopReloaded.Constants.PetShopReloadedStoreName);

}

return this._context;

}

}

public override CodeFluent.Runtime.BinaryServices.BinaryLargeObject LoadBinaryLargeObject(System.Web.HttpContext context, string propertyName, object[] identifiersValues)

{

if ((this.EntityClrFullTypeName == "PetShopReloaded.Item"))

{

PetShopReloaded.Item Item = PetShopReloaded.Item.Load(((int)(ConvertUtilities.ChangeType(identifiersValues[0], typeof(int), -1))));

if ((Item == null))

{

return null;

}

if ((propertyName == "Item_Image"))

{

return Item.Image;

}

}

if ((this.EntityClrFullTypeName == "PetShopReloaded.Product"))

{

PetShopReloaded.Product Product = PetShopReloaded.Product.Load(((int)(ConvertUtilities.ChangeType(identifiersValues[0], typeof(int), -1))));

if ((Product == null))

{

return null;

}

if ((propertyName == "Product_Image"))

{

return Product.Image;

}

}

return null;

}

}

Remembering the model of our application you will notice that this generated BLOB handler will be able to handle image from “Product” and “Item” tables, which also are the only entities where we defined properties of type “image”. Also you can check-out the Blob http Handler article for more information.

To conclude, we can say that CodeFluent Entities provides ready-to-use code for you developers allowing you to focus on the application you are working on.

NB. For our application Pet Shop Reloaded we have used the generated BOM classes in a Web context (ASP .NET MVC), but know that you can also use it in other contexts like a WPF or a Windows Forms application.

Cheers,

The SoftFluent Team.