Entity Framework and RIA Services do not allow Entities to be added/removed from cross containers. In order to move Entity from one DomainContext/ObjectContext to another DomainContext/ObjectContext, we need to recursively detach the object graph and attach it to other DomainContext/ObjectContext.

Object Graph

Single entity can be easily detached and attached from EntitySet where it belongs, but the problem comes when navigation properties of entity are not empty. Entity object along with navigation properties is called Object Graph because if you notice, navigation property’s navigation property will contain reference to same entity and that will result in endless recursive code for Detach/Attach.

An entity with the same identity already exists in the EntitySet

When you try to detach entity from old DomainContext/ObjectContext and attach it to DomainContext/ObjectContext, it may give you an error that entity with same identity already exists and it will throw an exception. In this case we will just simply reuse the existing entity instead of attaching the entity we have.

Entity cannot be attached to this EntityContainer because it is already attached to another EntityContainer

In case of ObjectGraph, your root level entity is already detached, but navigation properties are not detached, and while you try to attach your root level entity, it will throw same error for entities that exist in navigation properties.  Because detach method does not recursively detach every entity from navigation properties.

Attach/Detach Extension Methods

Finally after brainstorming little, I made following class that will allow you to recursively detach/attach object graphs from DomainContext. You can replace DomainContext to ObjectContext to use it inside Entity Framework.

DomainContext Extensions
  1. /// <summary>
  2. /// DomainContext Extensions
  3. /// </summary>
  4. public static class DomainContextExtensions {
  5.  
  6.     /// <summary>
  7.     /// Recursively Attaches entity loaded from Other DomainContext to
  8.     /// current specified DomainContext
  9.     /// </summary>
  10.     /// <param name="context">DomainContext where entity will be attached</param>
  11.     /// <param name="entity">Entity loaded from other DomainContext</param>
  12.     /// <returns></returns>
  13.     public static Entity Attach(this DomainContext context, Entity entity)
  14.     {
  15.         if (entity == null || entity.EntityState != EntityState.Detached)
  16.             return entity;
  17.  
  18.         Entity newEntity = entity;
  19.  
  20.         Entity[] list = new Entity[] { entity };
  21.         foreach (Entity c in context.EntityContainer.LoadEntities(list,
  22.             LoadBehavior.MergeIntoCurrent))
  23.         {
  24.             newEntity = c;
  25.             break;
  26.         }
  27.  
  28.         // recursively attach all entities..
  29.         Type entityType = typeof(Entity);
  30.  
  31.         // get all navigation properties…
  32.         Type type = entity.GetType();
  33.         foreach (var item in type.GetProperties())
  34.         {
  35.             if (entityType.IsAssignableFrom(item.PropertyType))
  36.             {
  37.                 Entity navEntity = Attach(context, item.GetValue(entity, null)
  38.                     as Entity);
  39.                 item.SetValue(newEntity,navEntity, null);
  40.                 continue;
  41.             }
  42.             if (item.PropertyType.Name.StartsWith("EntityCollection"))
  43.             {
  44.                 IEnumerable coll = item.GetValue(entity, null) as IEnumerable;
  45.                 List<Entity> newList = new List<Entity>();
  46.                 foreach (Entity child in coll)
  47.                 {
  48.                     newList.Add(Attach(context, child));
  49.                 }
  50.                 dynamic dcoll = item.GetValue(newEntity,null);
  51.                 foreach (dynamic child in newList)
  52.                 {
  53.                     dcoll.Add(child);
  54.                 }
  55.             }
  56.         }
  57.         return newEntity;
  58.     }
  59.  
  60.     /// <summary>
  61.     /// Recursively detaches entities from DomainContext, this
  62.     /// method detaches every navigation properties
  63.     /// of current Entity as well.
  64.     /// </summary>
  65.     /// <param name="context"></param>
  66.     /// <param name="entity"></param>
  67.     public static void Detach(this DomainContext context, Entity entity)
  68.     {
  69.         if (entity == null || entity.EntityState == EntityState.Detached)
  70.             return;
  71.         EntitySet nes = context.EntityContainer.GetEntitySet(entity.GetType());
  72.         nes.Detach(entity);
  73.  
  74.         Type entityType = typeof(Entity);
  75.  
  76.         // get all navigation properties…
  77.         Type type = entity.GetType();
  78.         foreach (var item in type.GetProperties())
  79.         {
  80.             if (entityType.IsAssignableFrom(item.PropertyType))
  81.             {
  82.                 Detach(context,item.GetValue(entity, null) as Entity);
  83.                 continue;
  84.             }
  85.             if (item.PropertyType.Name.StartsWith("EntityCollection"))
  86.             {
  87.                 IEnumerable coll = item.GetValue(entity, null) as IEnumerable;
  88.                 foreach (Entity child in coll)
  89.                 {
  90.                     Detach(context,child);
  91.                 }
  92.             }
  93.         }
  94.     }
  95.  
  96. }

Share
Tagged with:  

SQL Assembly brings power of CLR (Common language runtime) inside SQL Database Stored Procedure which can overcome T-SQL programming pains of Intellisense, Debugging, Logging and Versioning.

Traditional Problems with T-SQL and Stored Procedures

I never liked programming in T-SQL, for various reasons listed below,

  1. No Intellisense, of course it has been introduced SQL 2008 onwards, but still its far behind what we get in Visual Studio.
  2. Source Code Control, although scripts can be added to source code control, usually its unawareness and unwillingness of Database Administrator / Designer to use it correctly and mess things up.
  3. Less human readable, T-SQL is very difficult to understand if its not documented well.
  4. Source code is open, it can be modified, so in short Database Administrator has complete access to alter business logic.
  5. Very less reusable, unless you do copy paste, no way to standardize the development.
  6. No support for advanced visual tools to design T-SQL Stored Procedures.
  7. Deployment is difficult, minor alternation can cause problems.
  8. Most of business logic involves, loops, if-else, switch statements, and it takes 10 times more code to execute such logic in T-SQL then any other programming language in world.
  9. You need multiple language talent, one with either VB.NET/C# and T-SQL.
  10. Difficult to Log information.

Introduction of SQL Assembly

Since SQL 2005, introduction of SQL Assembly has been of great importance, however not much of people still use it, because of unawareness. But SQL Assembly can be modularized and reused, and it exists as simple CLR assembly inside database.

And following are benefits of SQL Assembly, besides few listed in MSDN here.

  1. LINQ in CLR Stored Procedure.
  2. Better Source Code control over Visual C#/Visual Basic.NET project through Team System.
  3. Intellisense.
  4. Closed source, its safe.
  5. Highly secure as Database Administrator can not alter business logic.
  6. C# and VB.NET along with LINQ are more human readable, understanding and reusing code can be very easy.
  7. Support for advanced documentation in comments.
  8. Visual Studio Model designer can be used.
  9. Reuse your Business Logic for other database vendor products, e.g. Oracle, MySQL (Explained below).
  10. You can do advanced logging with log-4-net or custom logging.

Small Example of How to use LINQ in SQL Assembly

  1. Create a simple Visual C# Class Library Project.
  2. Add reference of “System.Data” Assembly.
  3. Create new ADO.NET Entity Model, and you can create it from Database or empty model, the way you want to develop your project.
  4. Add few entities, I am going to demonstrate entity “Cart” which is a saved shopping cart for the Customer.

CartDemoCreate a Stored Procedure Class

After creating model, lets create a class called “ShoppingCart” and add a static method as shown below.

public class ShoppingCart
{

    /// <summary>
    /// Creates new Cart if none exists and returns the Cart ID
    /// </summary>
    /// <param name="CustomerID"></param>
    /// <returns></returns>
    [SqlProcedure]
    public static SqlInt64 GetSavedCartID(SqlInt64 CustomerID)
    {

        // Set context connection=true
        ShoppingCartModelContainer context =
            new ShoppingCartModelContainer("context connection=true");

        // Query for exisitng cart
        Cart c = context.Carts.FirstOrDefault(
                        t => t.CustomerID == CustomerID.Value);

        if (c == null) { 

            // create new Cart
            c = Cart.CreateCart(0, CustomerID.Value, DateTime.Now);
            context.AddToCarts(c);
            context.SaveChanges();
        }

        // return the Cart ID
        return new SqlInt64(c.CartdID);

    }

}

This code demonstrates how easy it is to write SQL Assembly, now here is the ultimate benefit of everything.

Ultimate Benefit

You can use your Business Logic in multiple vendor databases, like for example for Oracle and MySQL, you can reuse your SQL Assembly and just change your connection string. You can reuse your business logic in your front end code with simple wrapper.

And with SQL Server, you can reuse this assembly inside SQL Database.

CodeSharing

Share
Tagged with:  

This document only refers to optimization of Vista Machine for faster development only intended for the ones who are doing development on C#, ASP.NET and Optional VC++, no VB.NET.

Installation of Limited Visual Studio 2008

We probably dont need Compact Frameworks and VB.NET and other tools, unnecessary installing them doesnt waste much of Hard disk space but what happens that your registry grows too big as you install more number of items. Registry is very costly database, and its accessed very regularly, more items in registry, slower and slower the PC. So here is list of items you should install.

Visual Studio Items

Visual Studio Items

Disable High End Graphics, Faster Performance

Disable High End Graphics

Disable High End Graphics

Disable System Restore Points

Now, System Restore Points are good, but usually on development machine, they run very slow, and they never do any good if system crashes, the restore time is as big as and as problematic as to reinstall OS.

Disable System Restore Points

Disable System Restore Points

Increase Paging Size

Increase it as much as you can in different drive but the acceptable range is 2GB to 4GB only.

Increase Paging Size

Increase Paging Size

Remove Unnecessary Vista Items as shown below

Remove Unnecessary Programs and Features

Remove Unnecessary Programs and Features

Setup Taskbar and Start Menu

Taskbar and Startmenu Properties

Taskbar and Startmenu Properties

Expand Items for Quicker Use

Expand Control Panel

Expand Control Panel

Expand Documents

Expand Documents

Expand Admin Tools

Expand Admin Tools

Share
Tagged with: