Wednesday, May 28, 2008

ADO.NET Entity Framework - Part 3

ADO.NET Entity framework - update changes to the storage layer.

ADO.NET Entity framework helps you in creating, updating and deleting objects by using Object Services. Object Services keep track of the changes and then update them to the persisted storage by executing the corresponding T-SQL statements. The SaveChanges() method of the ObjectContext class is used for saving the changes to the persistence storage.

In this post I will explain how to apply changes on a detached object to the storage layer.

When a query is executed within an object context, the returned objects are automatically attached to the context. Object Services also lets you attach existing objects to an object context. Once you attach an object to the context. You can use the SaveChanges() method to update the changes in the database.

The ApplyPropertyChanges method can be used when the object already exists in the store and the detached object has property updates that you want to persist.

In the following example an updated Customer object is passed to the Save method. The Save method retrieves the original object by using the EntityKey and then updates the original object by the ApplyPropertyChanges() method. Later the changes are updated by using the SaveChanges() method of the ObjectContext class.

public int Save(Customer myCustomer)

{

EntityKey key;

object originalItem;

using (TwoWayDataBindingEntities entites = new TwoWayDataBindingEntities())

{

try

{

// Get the detached object's entity key.

if (myCustomer.EntityKey == null)

{

// Get the entity key of the updated object.

key = entites.GetEntityKey("Customers", myCustomer);

}

else

{

key = myCustomer.EntityKey;

}

// Get the original item based on the entity key from the context

// or from the database.

if (entites.TryGetObjectByKey(key, out originalItem))

{

// Call the ApplyPropertyChanges method to apply changes

// from the updated item to the original version.

entites.ApplyPropertyChanges(key.EntitySetName, myCustomer);

}

return entites.SaveChanges();

}

catch (InvalidOperationException ex)

{

//Exception handling logic

}

return 0;

}

}

Wednesday, May 21, 2008

ADO.NET Entity Framework - Part 2

Working with ADO.NET Entity framework

After looking into the architecture of the Entity Framework, this article I will show the how to create an EDM using the Entity Data Model Wizard.

The Entity Framework compiles a set of conceptual and storage schemas, together with the mappings between them, into bidirectional pairs of Entity SQL statements called client views. These views drive query and update processing in the runtime engine.

Generating an Entity Data model

To generate an EDM you need to first add an ADO.NET Entity Data Model item template to the project. Follow the below given steps to add and EDM to the project

  1. Right-click the project, point to Add, and then click New Item.
  2. Select ADO.NET Entity Data Model in the Templates pane.
  3. Click Add after you enter the name for EDM. This will present the Entity Data Model Wizard.
  4. Select Generate from database in the Choose Model Contents dialog box. Then click Next.
  5. Click the New Connection button. The Connection Properties dialog box is displayed.
  6. Enter your server name, select the authentication method.
  7. Select the database name, and then click OK.
  8. The Choose Your Data Connections dialog box is updated with your database connection settings.
  9. Select all the tables from the dialog box and click Finish.

The Entity Framework tools generate a class derived from ObjectContext that represents the entity container defined in the conceptual model. The ObjectContext class supports queries against an EDM that return entities as objects, as well as creating, updating, and deleting entity objects. The Entity Framework supports object queries against an EDM. Queries can be composed using Entity SQL, LINQ to entities and object query builder methods.

Once the entity data model is generated you can use any of the above given methods to query your ObjectContext class.

For example :

using (BlogEntities entities = new BlogEntities())

{

var query = from blogentry in entities.blogentries

.Skip(StartRow).Take(PageSize)

orderby blogentry.datepublished descending

select blogentry;

return query;

}

Tuesday, May 13, 2008

Accessing anonymous types from a different assembly

Anonymous types are one of the new features introduced in C# 3.0 which helps you to encapsulate a set of properties into an object without having to define a type. The type will not be available at the source code level (This is generated by the compiler).

In this article I will explain how to access anonymous types exposed from another assembly in the caller method. There are some very nice articles on the topic by Tom and Clark .

I have a GetContactList method which returns an anonymous type collection that is a result of the LINQ query.

public class Contact

{

public Int32 ContactID { get; set; }

public String ContactName { get; set; }

public Int32 CompanyID { get; set; }

}

public class Company

{

public Int32 CompanyID { get; set; }

public String CompanyName { get; set; }

public String CompanyURL { get; set; }

}

public Object[] GetContactList()

{

var contacts = from contact in GetContacts()

join company in GetCompanies()

on contact.CompanyID equals company.CompanyID

select new { contact.ContactName, company.CompanyName, company.CompanyURL };

return contacts.ToArray();

}

The properties of this return type cannot be accessed before casting it to an object.

The type returned from the above method looks something like this to the external caller.

<>f__AnonymousType0`3[System.String,System.String,System.String] b__3(BusinessCoreLayer.Contact, BusinessCoreLayer.Company)

I will go through some interesting parts of the above type

  • The 0 after the <>f__AnonymousType is a zero based index of each anonymous type definition. (If you have another anonymous type in the code that will have the index 1)
  • The 3 after the 0 represents the number of properties in the anonymous type (We have 3 properties – ContactName, CompanyName, CompanyURL)
  • The rest of the portions represent the data types and method name

I have created an Entity converter that will convert this anonymous type to the respective type in the caller function. The below given code will convert the anonymous type collection returned to the ContactDetails object.

public class ContactDetails

{

public String ContactName { get; set; }

public String CompanyName { get; set; }

public String CompanyURL { get; set; }

}

private ContactDetails EntityTranslator(Collection<KeyValuePair<String, Object>> propertyCollection)

{

ContactDetails cd = new ContactDetails();

foreach (KeyValuePair<String, Object> propertyInfo in propertyCollection)

{

switch (propertyInfo.Key)

{

case "ContactName":

cd.ContactName = propertyInfo.Value.ToString();

break;

case "CompanyName":

cd.CompanyName = propertyInfo.Value.ToString();

break;

case "CompanyURL":

cd.CompanyURL = propertyInfo.Value.ToString();

break;

}

}

return cd;

}

Now in the caller method I have to call the EntityTranslator like

Object[] contacts = Assembly2.GetContactList();

Collection<ContactDetails> details = new Collection<ContactDetails>();

foreach (Object contact in contacts)

{

ContactDetails cd = new ContactDetails();

Type t = contact.GetType();

PropertyInfo[] pInfo = t.GetProperties();

Collection<KeyValuePair<String, Object>> propertyCollection = new Collection<KeyValuePair<String, Object>>();

foreach(PropertyInfo pi in pInfo)

{

propertyCollection.Add(new KeyValuePair<String, Object>(pi.Name, pi.GetValue(contact, null)));

}

cd = ContactTranslator(propertyCollection);

details.Add(cd);

}

As you have seen by using Reflection we can access the properties of anonymous type returned from another assembly.

Friday, May 9, 2008

ADO.NET Entity Framework - Introduction

I have been using LINQ to SQL as an OR-mapper for my application since the release of Visual studio 2008. As a light weight OR-mapper and for RAD scenarios LINQ to SQL serves my purpose as a framework for persisting data. But when thinking about Enterprise Application development and real scenarios, I don’t find LINQ to SQL as powerful tool with all the features I require for Application development.

LINQ to SQL as present was not a competitor for NHibernate or LLBLGen which are the common OR-mappers available. If you are looking for a better OR-mapper from Microsoft, ADO.NET Entity framework is the answer. This one gives life to the conceptual modeling and has a lot of features compared to LINQ to SQL. The primary benefit of the ADO.NET Entity Framework is to elevate the level of abstraction at which developers can work when they deal with data and to decrease the amount of code that is required to create and maintain data-oriented applications.

Some of the advantages of using Entity framework:

  • Entity framework maps relational tables, columns, and foreign key constraints to entities and relationships in conceptual models. Instances of these classes are populated with data and data changes are saved based on defined mappings between the conceptual and storage model.
  • Supports Entity SQL and LINQ to Entities two powerful query languages to query the data.
  • Provides a rich and intuitive view to the data model from the application perspective as opposed to the normalized view of data.
  • Last but not least, comes with a code generation wizard that is integrated with Visual Studio that will create less and more quality code much faster.

In this article series I will be explaining the underlining technologies in the Entity Framework by some tutorials that help you to get hands on experience on the topic.

The architecture

The ADO.NET Entity Framework is a layered framework which abstracts the relational schema of a database and presents a conceptual model.

  • Object Services: Object Services is a component of the Entity Framework that enables you to query, insert, update, and delete data, expressed as strongly-typed CLR objects that are instances of entity types. Object Services supports both Language-Integrated Query (LINQ) and Entity SQL queries against types defined in an Entity Data Model (EDM). Object Services materializes returned data as objects, and propagates object changes back to the persisted data store. It also provides facilities for tracking changes, binding objects to controls, and handling concurrency. Object Services is implemented by classes in the System.Data.Objects and System.Data.Objects.DataClasses namespaces.
  • Entity SQL: Entity SQL is a SQL-like language provided by the ADO.NET Entity Framework to support the Entity Data Model (EDM). The EDM is an extended relational model that supports basic relational concepts, rich types with inheritance, and relationships. Entity SQL supports EDM constructs, enabling users to effectively query the data represented by an entity model.
  • Entity Data Model: The Entity Data Model (EDM) is a specification for defining the data used by applications built on the Entity Framework. Applications using the EDM define entities and relationships in the domain of the application in a design schema. The design schema is used to build programmable classes used by application code. The entity data model contains of 3 parts
  1. Conceptual Schema Definition Language (CSDL): The conceptual schema is a design template for the object model that will be used by applications built on the Entity Data Model (EDM). Conceptual schema is used to declare and define entities, associations, inheritance etc. It is from this schema the Entity classes are generated.
  2. Store schema definition language (SSDL): The SSDL is a formal description of the database that persist data for an application built on the Entity Data Model (EDM). The entities and associations declared in this schema are the basis for mapping entities and associations in the conceptual schema to the corresponding entities in the storage model. This contains the metadata describing the database that persist data.
  3. Mapping specification language (MSL): In the Entity Data Model (EDM), the mapping specification uses mapping specification language (MSL) to connect the types declared in conceptual schema definition language (CSDL) to database metadata that persists data for applications that use the object model being defined.
  • LINQ to entities: LINQ to Entities enables developers to write queries against the database from the same language used to build the business logic

In In the next part of this series we will look into more details of the Entity Framework and see how Entity Framework will assist in creating data centric applications more easily.

Wednesday, May 7, 2008

FxCop Rules, Causes and Fixes - Part 2

Continuing the previous article on FxCop rules. I have added some more rules and their reasons.


Rule: StaticHolderTypesShouldNotHaveConstructors

Cause: A Public type declares only static members and has a public or default constructor.

Fix: Remove the public constructor and replace that with a private constructor.

Rule: StaticHolderTypesShouldBeSealed

Cause: A Public type declares only static members is not declared with a sealed modifier

Fix: Mark the type as sealed.

Rule: IdentifiersShouldHaveCorrectSuffix

Cause: Types that extend certain base types or that implement certain interfaces, or types derived from these types, have a suffix that is associated with the base type or interface.

The following table lists the base types and interfaces that have associated suffixes.

Base type/Interface

Suffix

System.Attribute

Attribute

System.EventArgs

EventArgs

System.Exception

Exception

System.Collections.ICollection

Collection

System.Collections.IDictionary

Dictionary

System.Collections.IEnumerable

Collection

System.Collections.Queue

Collection or Queue

System.Collections.Stack

Collection or Stack

System.Collections.Generic.ICollection

Collection

System.Collections.Generic.IDictionary

Dictionary

System.Data.DataSet

DataSet

System.Data.DataTable

Collection or DataTable

System.IO.Stream

Stream

System.Security.IPermission

Permission

System.Security.Policy.IMembershipCondition

Condition

An event-handler delegate.

EventHandler

Fix: Rename the type so that it is suffixed with the correct term.

Rule: IdentifiersShouldNotContainUnderscores

Cause: identifier contains the underscore (_) character.

Fix: Remove the underscore.

Rule: UriPropertiesShouldNotBeStrings, UriParametersShouldNotBeStrings, UriReturnValuesShouldNotBeStrings

Cause: A Property, Parameter or a method that contains Uri, Url etc in the name is declared as a String. A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The System.Uri class provides these services in a safe and secure manner.

Fix: Change the return type to Uri.

Rule: DoNotDeclareVisibleInstanceFields

Cause: An externally visible type with modifiers (Public, Protected/ Protected Internal) has an externally visible instance field.

Fix: Make the externally visible field private or internal and expose it using an externally visible property.

Rule: DoNotInitializeUnnecessarily

Cause: A field is initialized to its default value. The common language runtime initializes all fields to their default values before running the constructor. In most cases, initializing a field to its default value in a constructor is redundant, which degrades performance and adds to maintenance costs.

Fix: Remove the unnecessary initializations.

Rule: IdentifiersShouldBeCasedCorrectly

Cause: The name of an identifier is not cased correctly. By convention, parameter names use camel casing; namespace, type, and member names use Pascal casing. In a camel-cased name, the first letter is lower case, and the first letter of any remaining words in the name is in uppercase. In a Pascal-cased name, the first letter is upper case, and the first letter of any remaining words in the name is in uppercase.

Fix: Change the name so that it is cased correctly.

Rule: CompoundWordsShouldBeCasedCorrectly

Cause: The name of an identifier contains multiple words and at least one of the words appears to be a compound word that is not cased correctly.

Fix: Change the name so that it is cased correctly.

Rule: IdentifiersShouldNotMatchKeywords

Cause: A namespace name or a type name matches a reserved keyword in a case-insensitive comparison. Using a reserved keyword as the name of a virtual/interface member makes it harder for consumers in other languages to override/implement the member.

Fix: Change the name to something that does not appear in the list of keywords.

Rule: PropertyNamesShouldNotMatchGetMethods

Cause: The name of a public or protected member starts with 'Get' and otherwise matches the name of a public or protected property.

Fix: Change the name so that it does not match the name of a method prefixed with 'Get'.

Tuesday, May 6, 2008

FxCop Rules, Causes and Fixes - Part 1

Using FxCop as a code analysis tool provides a lot of benefits in fixings the errors / coding standards in the application. I will try to list out the common errors and fixes for those errors.

Rule: MarkAssembliesWithClsCompliant

Cause: Assemblies should explicitly indicate CLS compliance with CLSCompliantAttribute. If the attribute is not present on an assembly, the assembly is not CLS compliant. Assembly does not have the System.CLSCompliantAttribute attribute applied to it.

Fix: Add the reference to the namespace System in the AssemblyInfo.cs file and add the attribute [assembly: CLSCompliant(true)] to the file

Rule: AvoidNamespacesWithFewTypes

Cause: A namespace other than the global namespace contains fewer than five types.

Fix: Combine namespaces that contain a small number of types (Less than 5) into a single namespace.

Rule: AssembliesShouldHaveValidStrongNames

Cause: An assembly is not signed with a strong name, the strong name could not be verified, or the strong name would not be valid without the current registry settings of the computer. You have delay signed the assembly. You have used the strong name tool to skip verification for the assembly.

Fix: Create a strong name file using the sn tool and sign the assembly.

Rule: LongAcronymsShouldBePascalCased

Cause: The name of an identifier contains an acronym of three or more uppercase letters

Fix: Change any three-letter acronyms in the name to Pascal case, and change any two-letter acronyms to uppercase

Rule: ShortAcronymsShouldBeUppercase

Cause: The name of an identifier contains a two-letter acronym and the second letter is lowercase.

Fix: Change the second letter of acronym to upper case.

Rule: UsePropertiesWhereAppropriate

Cause: A public method that does not take a parameter starts with a Get and does not return a collection.

Fix: Change the method to a property.

Rule: AvoidUninstantiatedInternalClasses

Cause: Internal classes that are not instantiated in the assembly. The class may have only static members.

Fix: Create a private constructor to prevent the compiler creating an instance of the class.

Monday, May 5, 2008

Strong Naming The Enterprise Library

Enterprise Library comes with a collection of application blocks and guidance documents that together provide functionality common to enterprise applications. But most of the users of the application blocks would have faced the problems with the application blocks assembly when you try to strong name your assemblies which have references to the Enterprise Library

Reason:

Enterprise Library assemblies are not strong named

You need to sign the enterprise library assemblies if you want to install it into the GAC/ to add a reference to a strong named assembly.

In this article I will explain how to delay sign your Enterprise Library assemblies and use it with a strong named assembly.

Tom Hollander has mentioned the process of strong naming the Enterprise library assemblies in his post on Enterprise Library Update and Strong Naming Guidance Package

In this article I will explain the entire process of strong naming the enterprise library assemblies with details that may help the users using Enterprise Library in their applications.

Using the Strong Naming Guidance Package

  1. Open the EntrpriseLibrary.VSTS solution in Visual Studio.
  2. Ensure that you have GAX and Strong naming guidance package installed on your system.
  3. On Visual Studio select Tools->Guidance Package Manager
  4. Select 'Enable/ Disable Guidance Packages'
  5. Select the Strong Naming Guidance packages.
  6. Right-click on a project/ solution folder and choose "Create a new strong-name key pair file". This will create a string name key file for signing the assemblies.
  7. Right-click on the project/ solution folder and choose "Strong-name all projects in this solution or solution folder".
  8. Use the key file created in step 6 for strong naming the assemblies. Also select the "Update InternalsVisibleTo" checkbox to tell the recipe to search for this attribute and add the public key.
  9. Press OK and the strong name guidance package will do the rest for you.
If you don't have the Strong Naming Guidance Package installed in your system you can manually configure the assemblies by following the steps given below.

  • Open the visual studio command prompt and create a strong name key file.
  • Extract the public key file from the strong name file.
  • Use sn-tp to see the hex decimal form of the public key from the public key file, and copy the hex key to a notepad for later use.
  • Now open the enterprise library source code and then delay sign the projects using the public key file. For that right click the project and select Add Existing Item

  • Open the folder where the public key file is stored. Select the public key file and click on Add as link in the dialog box. This will add the reference to the key file.
  • Right click the project and select properties.
  • On the signing tab check the Sign the assembly check box and select the public key file name displayed in the drop down list.
  • Check the delay sign only check box also.

  • Now search for “InternalsVisibleTo in the entire solution and add the PublicKey= option to the attribute. (Use the hex value that is copied in step 3 for this) Eg: [assembly: InternalsVisibleTo("Microsoft.Practices.EnterpriseLibrary.Caching.Tests,

PublicKey=002400000480000094000000060200000024000052534131000400000100010011
fc4f9f791dbe3a2ce058
c143dcebb2580f5a081ace54c5980b2233da323df8a7a3000d318bfb
9faaa407d2d75d47158ff3eabf6e7e365561ecb5317a1903efd9f281135399e17ecdacd94a37
d14f2923451000abf6658c18f988b591bd45af44b057cb71f4825bed259268e187d0a75ce7f5
dee2c84d43ccd3e
7d66d2509cf")]

  • Now rebuild the entire solution.
  • Use the sn-Vr option to skip verification for the assemblies.