Saturday, June 14, 2008

An implementation of a Generic Container for WCF

I am currently writing a service using WCF.  One of the things that I need to expose is a container that wraps my results to provide counts. I came up with the below implementations.  One of the things that becomes a problem is the resulting serialization of the container name. By default, the serialized object would be ContainerOf[T].  By defining a name with a String.Format type of syntax, [DataContract(Name="{0}sContainer")].  Would create  the following for the Apple object: ApplesContainer.

Enjoy

/// <summary>
/// Generic Container for holding results
/// </summary>
/// <typeparam name="T"></typeparam>
[DataContract(Name="{0}sContainer")]
public class Container<T>
{
    /// <summary>
    /// TotalResults that can be returned.
    /// </summary>
    [DataMember]
    public int TotalResults
    {
        get;
        set;
    }

    /// <summary>
    /// Container results.
    /// </summary>
    [DataMember]
    public IEnumerable<T> Results
    {
        get;
        set;
    }
}

 

References:

Part 2: Using LINQ XML in your Unit Testing

Technorati Tags: ,,

In Part 1, we talked about creating LINQ objects and getting data. This time, we are going to show how to use XML with LINQ to test a SQL database. This part is really not difficult, we are just going to cover the basics of getting started. I have made the conscious decision that I am going to use a SQL database during my development process. You may decide that you want to do use a different methodology. These are some of your options:

Step 1: Generate Data
First, you want to create some test data. Since, I did not really wanted to do this by hand I found a site www.generatedata.com, that has an online utility for generating data. The best part was the different formats that it supports.

Step 2: Create Unit Test Projectimage
Now that I have data, I created a Unit Test project and now I am ready to really get some work done. In this project, I created a "Data" directory and put my generated XML from Step 1. To the right is an example of what my Unit Testing file structure currently looks like.

Step 3: Create Helper
The next thing we want to do is create a helper that will be used to populate XML data to SQL. Next, lets create a class, and name it CustomerHelper. In my class, I made the following adjustments.

  • References
    • Business Library where my model LINQ objects are held.
    • System.Linq
    • System.Xml.Linq
  • Make the class static. (See below sample)

Next, we need to add some constants to hold the XML and resulting collections that will get loaded. Mine looks like the following:

    public static class CustomerHelper{
        static XDocument xmlCustomers;
static List customers;
        public static List<Customer> Customers
{
get { return customers; }
}
}

Next we need to automatically load the data in the constructor.

            xmlCustomers = XDocument.Load("Customers.xml");
customers = (from c in xmlCustomers.Descendants("Customer")
select new Customer
{
FirstName = (string)c.Element("FirstName"),
LastName = (string)c.Element("LastName"),
MiddleName = string.Empty,
Apartment = string.Empty,
Address = (string)c.Element("Address"),
City = (string)c.Element("City"),
Country = "USA",
Email = (string)c.Element("Email"),
PostalCode = (string)c.Element("PostalCode"),
State = (string)c.Element("State"),
Telephone = (string)c.Element("Telephone"),
}
).ToList();

So some explaining, need to be done about what is happening here. First we are loading the XML file into an XDocument. That XDocument will then act just like SQL where we can query against it like any other data. LINQ looks at the object just like it would for SQL except there are some additional properties and methods. An example of the data is below. We query the data and turn it into LINQ SQL objects. The query is doing the following:




  1. Query the xmlCustomer object looking for the "Customer" nodes.

  2. In each customer node, we want to take the selected elements and populate them into our Customer object.

  3. After building the query, execute the code now and return a list of Customers.


 <Customers>
<Customer>
<FirstName>Bevis</FirstName>
<LastName>Dalton</LastName>
<Address>5394 Dis Ave</Address>
<City>Tamuning</City>
<State>Wisconsin</State>
<PostalCode>04338</PostalCode>
<Telephone>(772) 462-2385</Telephone>
<Email>lorem.luctus.ut@elitEtiam.ca</Email>
</Customer>
</Customers>


If we try and run this now, it will not work because we need to do a little bit of plumbing first.


Step 4: Start Testing


After creating my unit test file, I add a reference to my LINQ Database Context, which in my case is called InventoryDBDataContext.

        InventoryDBDataContext db;
In my Test Initialize I create an instance of my database context, so each test will have a new one.

        [TestInitialize()]
public void MyTestInitialize()
{
db = InventoryDBDataContext.Create();
}

Now I just want to do a simple test to make sure that I can get data from XML and into SQL.


        [TestMethod]
[DeploymentItem(@"\Data\")]
public void ShouldCreateAGroupOfCustomers()
{
ShouldDeleteAllCustomers();
foreach (Customer cust in CustomerHelper.Customers)
{
db.Customers.InsertOnSubmit(cust);
db.SubmitChanges();
}
Assert.IsTrue(db.Customers.Count() >= 5);
}

public void ShouldDeleteAllCustomers()
{
foreach (Customer c in db.Customers)
{
db.Customers.DeleteOnSubmit(c);
}
db.SubmitChanges();
Assert.IsTrue(db.Customers.Count() == 0);
db.ExecuteCommand("
DBCC CHECKIDENT ('Customer', RESEED, 0)");
}

The key to this whole process is the [DeploymentItem(@"\Data\"] attribute. This takes the XML files and makes sure that they are deployed with the rest of the files. The other key is that I want to clean up my SQL database after each test, so I clear out my data and make sure that the Identity field gets reset so it matches the other XML data which will be used later.
So, now we are done.  You should have working test, that can take XML data and put it into SQL for Data Populate, but you also have a set of data that you can then run test against and test that you got correct results.

In the next installment, we will examine the full completed LINQ middle tier of our application.

Have fun.



Are you using LINQ? Lets get started.

So, I am going to talk about LINQ.  There are a lot of great resources out there on LINQ.  I am going to have a series of articles on building an application utilizing LINQ, WCF and other technologies. Some of the things that I want to show is how you can use LINQ as part of your testing.  So lets get started.Customer Definition

So the first thing that we need is some data to define. The sample application that we are going to build is a simple home inventory system.  The image to the right defines a Customer. 

There is three ways that we can generate this data definition.

  1. (SqlMetal.exe)
  2. Designer Wizard (.dbml)
  3. Manually (.cs)

The second option is the simplest but you don't have very much control of what gets generated. So, I favor creating my files manually, because I have total control and I only define what I need (Option 3).

Step 1: Define data class.

Make sure that you have a reference to System.Data.Linq.





Customer Definition(partial)  
    [Table(Name="Customer")]
public class Customer
{
[Column(Name="Id",
IsDbGenerated=true,
DbType="int",
IsPrimaryKey=true)]
public int Id
{
get;
set;
}

[Column(Name="FirstName")]
public string FirstName
{
get;
set;
}
}

To the left is my definition of my Customer table.  What we essentially doing is marking up a class, that LINQ will use to communicate to our database.  This class communicates several key pieces of information to us.  The data table, fields and keys that we define as important.




So starting at the top, we have defined that our Customer class will talk to the Customer table.  This could be a view or a stored procedure.  The [Table(Name="Customer")] attribute handles this for us.  We can do other advanced features, but we will talk about those at a different time.





Next, notice each property is marked with a [Column(Name=?)] column attribute.  This allows LINQ to map your database column with your physical class properties. This allows the flexibility to have different database column names than what you want to expose to your code.  There are additional attributes that allow you to set the Database type, and constraint information.





Last, you will notice that the Id field has some of those additional properties. We are telling LINQ that the Id field is an identity field, or SqlType "int" and is a primary key.  If you want LINQ to handle some of your data input automatically, you have to be verbose on your Column Attribute definitions to handle your constraints and keys.  If this case, since we setup keys on our tables and we want to use those keys to get data.  We have to make sure that LINQ knows that and we will use this in the future.




Step 2: Create Data Context



In this step we are going to create a data context to handle our database interactions.  First, we need to create a class that derives from System.Data.Linq.DataContext.   Second, we create a static Create method to handle the initialization of the class for ease of use.  Third, define tables, procedures and queries.  Below show a simple class for our use.



    public class InventoryDBDataContext : DataContext
{
public InventoryDBDataContext(string connection)
: base(connection)
{
}

public static InventoryDBDataContext Create()
{
string connection = ConfigurationManager.ConnectionStrings["InventoryDB"].ConnectionString;
return new InventoryDBDataContext(connection);
}

public Table<Customer> Customers;
}


You will notice that the static Create method allows for the hiding of implementation.  In the next part you will see how this is helpful.




Step 3: Get Data



Well, we finally are ready to get data.  To get a list of customer, all that we have to do is the following:



using (InventoryDBDataContext context = InventoryDBDataContext.Create())
{
var customers = (from c in context.Customers
select c).ToList();
Assert.IsTrue(customers.Count > 0);
}


Now you see that we are now containing the calls with a "using" statement. This allows for better garbage collection.  With the 3.0 framework, you can allow a runtime definition of variables by just using the "var" keyword.  The selection of the data looks very familiar with TSQL statements.  The selection pieces defined:



























TSQL Query Definition
from c in context.Customers Search all customers from the Database.
select c return the selected customers as a whole Customer object.
.ToList() Immediately execute the LINQ query.


 



We have now completed the basics with getting started with LINQ.  Next time we will take a deeper look into LINQ queries and other customization  of our classes.



Let me know what you think.  Next time we will cover how to use XML LINQ in unit testing our code.



David Waddleton



Links: