Archive of posts filed under the Data category.

Silverlight 4 + COM + SQL Server = Cool!

Today is the day to talk about COM possibilities in Silverlight 4.  One would question the titles of my post.  COM and Cool in the same sentence?  Let me proof this title to you.

First, let me take a closer look at COM.  In order to access COM, you must install Silverlight application on a local machine.  The access to COM is not enabled when a Silverlight application is run in the browser.  So, first of all you have to enable this by checking “Enable running application out of browser” checkbox in project properties.  Second of all, you have to check “Require elevated trust…” checkbox in “Out-of-browser settings” area in project properties.  Now, you are ready to install you application and test COM support.  How about Word automation:

Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
var doc = word.Documents.Add();
var paragraph = doc.Paragraphs.Add();
paragraph.Range.Text = "Some text";

Now, let’s talk about database access.  Parts of System.Data.SqlClient namespace are not exposed to COM by default.  So, to enable database access we must write an assembly that is exposed to COM that wraps database access.  To do so, check the property “Register for COM Interop” in project properties for the .NET (NOT Silverlight) based project that will fire off database queries for us.  Once the assembly is built, I can just use RegAsm to register my DLL with COM on a machine.  Of course, this would be a prerequisite to use Silverlight application for local data access.  The other prerequisite is to have .NET Runtime installed on that machine as well.  I could write an install project of course to make this process easier.

The next step is to write a Silverlight assembly that would use COM Interop similar to the one above for Word to talk to my database access .NET based assembly.

dynamic sqlDB = ComAutomationFactory.CreateObject("COMSQLClient.COMSqlDatabase");

Now the most exciting part.  I created and published the project on CodePlex that does exactly what I just talked about.  Check out the project and let me know what you think.  You can download the source code and look into the implementation details.  Here is the link to it:

http://silverlight4sqllib.codeplex.com/

Thanks.

Entity Framework 4.0 and Multiple Data Contexts

In the EF version 1.0, there was a problem when one would try to update multiple contexts as part of a single transaction.  For example, I can use Transaction Scope, the update one context, then second context.  Here is sample code to illustrate:

 

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using (RolodexEntities context = new RolodexEntities())
        {
            context.Connection.Open();

            Company company = new Company();
            company.CompanyName = "Test 1";
            company.DateAdded = DateTime.Today;
            context.AddToCompanies(company);
            context.SaveChanges();

            using (RolodexEntities context2 = new RolodexEntities(context.Connection as EntityConnection))
            {
                Company company2 = new Company();
                company2.CompanyName = "Test 1";
                company2.DateAdded = DateTime.Today;
                context2.AddToCompanies(company2);
                context2.SaveChanges();
            }
        }

        scope.Complete();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

This code in version 1.0 would throw an exception when second context’s constructor was called.  The exception was quite obscure and was referring to the fact that the connection was already open.  This was actually correct, but that was the whole reason I was passing in the connection.  I was trying to make sure that my transaction would not get promoted to Distributed Transactions Coordinator.  The transaction would always get promoted as soon as there are multiple SQL Server connections used within using scope/.end using scope code block.  So, in version 1.0 MSDTC would be required in the code above.

This issue still exists in EF 4.0.  You can vote to fix the issue here : https://connect.microsoft.com/data/feedback/details/533240/cannot-share-a-store-connection-between-multiple-contexts-in-order-to-avoid-dtc-promotion

Here is the code that confirms the problem:

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using (RolodexEntities context = new RolodexEntities())
        {
            context.Connection.Open();

            Company company = new Company();
            company.CompanyName = "Test 11";
            company.DateAdded = DateTime.Today;
            context.AddToCompanies(company);
            context.SaveChanges();

            RolodexEntities1 contextTemp = new RolodexEntities1();
            MetadataWorkspace space = (contextTemp.Connection as EntityConnection).GetMetadataWorkspace();
            EntityConnection connection = new EntityConnection(space, (context.Connection as EntityConnection).StoreConnection);

            using (RolodexEntities1 context2 = new RolodexEntities1(connection))
            {
                User user = new User();
                user.UserName = "test";
                user.Role = "User";
                context2.AddToUsers(user);
                context2.SaveChanges();
            }
        }

        scope.Complete();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Please feel free to ask any questions on this subject.

RIA Services (Cont.)

In this post I will cover the update process.

I am going to recap where I left off in the last post on RIA Services.  The last step was to retrieved based on ID from a read only company object.  Once this object is obtained in the VIewModel, we can create a screen to edit a company.

Here is how I am getting the company by ID in the ViewModel class:

var

companyQuery = _context.GetCompanyQuery(_companyID);

 

_context.Load<Companies>(companyQuery, (o1) =>

 

{

 

    HidePleaseWaitMessage();

 

    if (o.Error != null)

 

    {

 

        ErrorHandler.HandleException(o.Error);

 

    }

 

    else

 

    {

 

        this.Model = o1.Entities.First() as Companies;

 

    }

 

}, null);

Now that I have my Model property set, I can create a user control to edit the company.  Here is the part of the XAML for the edit form that shows the binding:

<UserControl x:Class

=”Rolodex.Silverlight.Views.CompanyEditView”

 

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

 

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

 

    xmlns:controls=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”

 

    xmlns:input=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls”

 

    xmlns:cal=”clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation”

 

    xmlns:core=”clr-namespace:Rolodex.Silverlight.Core”

 

    >

 

    <UserControl.Resources

>

 

       

 

    </UserControl.Resources

>

 

    <Grid x:Name

=”LayoutRoot”>

 

        <Grid.RowDefinitions

>

 

            <RowDefinition Height

=”*”/>

 

            <RowDefinition Height

=”Auto”/>

 

        </Grid.RowDefinitions

>

 

        <Grid x:Name=”EditGrid” DataContext=”{Binding Model

}”>

 

            <Grid.RowDefinitions

>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”1*”/>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”1*”/>

 

                <RowDefinition Height

=”35″/>

 

            </Grid.RowDefinitions

>

 

            <Grid.ColumnDefinitions

>

 

                <ColumnDefinition Width

=”Auto”/>

 

                <ColumnDefinition Width

=”200″/>

 

                <ColumnDefinition Width

=”*”/>

 

            </Grid.ColumnDefinitions

>

 

            <TextBlock Text=”Company Name:” TextAlignment=”Right” HorizontalAlignment=”Right” Grid.Column=”0″ Grid.Row=”0″ Margin=”6,6,6,6″ VerticalAlignment

=”Center”/>

 

            <TextBox x:Name=”CompanyNameTextbox” Grid.Column=”1″ Grid.Row=”0″ HorizontalAlignment=”Stretch” Margin=”6,6,6,6″ Text=”{Binding Path=CompanyName, Mode=TwoWay}” VerticalAlignment

=”Center”/>

 

            <TextBlock Text=”Date Added:” TextAlignment=”Right” HorizontalAlignment=”Right” Grid.Column=”0″ Grid.Row=”1″ Margin=”6,6,6,6″ VerticalAlignment

=”Center”/>

 

            <input:DatePicker x:Name=”DateAddedTextbox” SelectedDate=”{Binding DateAdded, Mode=TwoWay}” Grid.Column=”1″ Grid.Row=”1″ HorizontalAlignment=”Stretch” Margin=”6,6,6,6″ VerticalAlignment=”Center”/>

So far, I have an instance of a Companies object that is bound to the data context of my user control.  At this point a user can edit company name and date added fields.  Logically, the next thing a user would want to do is to save his changed – the nerve of him :-)

So, let’s take a look at the Save command in our view model object.

 

protected

override void BeginSave()

 

{

 

    ShowPleaseWaitMessage();

 

    _context.SubmitChanges(HandleSave, null);

 

}

 

 

 

private

void HandleSave(SubmitOperation operation)

 

{

 

    HidePleaseWaitMessage();

 

    if (operation.Error != null)

 

    {

 

        ErrorHandler.HandleException(operation.Error);

 

    }

 

}

Save is a two step process because all communication in Silverlight is asynchronous.  We are starting the save process in BeginSave, and we are checking for errors in HandleSave methods respectively.  The key part to this process is client side context of RIA Services that keeps track of all the changes that the user is making after the object has been initially retrieved via a call to the server.  The key work is done by the domain service object – LinqToEntitiesDomainService<RolodexEntities> in our case.  We can look at this code generated by the RIA Services wizard by looking at RolodexDomainService.cs class in my case.  There is a bug in current CTP that causes update to parent and child objects not being flushed properly.  In my case I have Companies object that contains a list of ComanyContacts objects.  Generated code has check for EntityState in UpdateCompanyContacts method that I had to remove to get the process to work.  Here is the final version of key methods of the Domain service class:

public

void UpdateCompanies(Companies currentCompanies)

 

{

 

    this.ObjectContext.AttachAsModified(currentCompanies, this.ChangeSet.GetOriginal(currentCompanies));

 

}

public

void UpdateCompanyContacts(CompanyContacts currentCompanyContacts)

 

{

 

    this.ObjectContext.AttachAsModified(currentCompanyContacts, this.ChangeSet.GetOriginal(currentCompanyContacts));

 

}

So, after this step all parts of the process are working – I can update companies and contacts.

Please email me any questions,

Velocity Presentation

As I mentioned previously, I presented on the topic of Velocity at the Atlanta Leading Edge Microsoft Users Group on Tuesday, January 19th.

The talk went pretty well, we had a lot of technical questions.  I really enjoyed this presentation, as I am always excited to speak on a new topic that I have not covered previously. 

You can download materials here.

 

Please let me know if you have any questions.

RIA Services (Cont.)

I am going to continue exploring the topic of RIA services and Silverlight.  I thought I was going to get into updates in this post, but there are a few topics I would like to cover first.  I am going to try to get to updates in the next post.

Today, I am going to explore two more topics.  I am going to cover extending RIA Services DomainContext with custom classes and working on including child objects when fetching a parent object using Entity Framework and RIA Services.

 

First, I am going to extend my DomainContext with a custom class.  In my case I have Company Object/Table with a number of columns.  In my Silverlight application I would like to have a list of companies that shows only company name.  When a user selected one company, I would like to fetch full company object with company contacts child object.  If I were to use the method that the wizard built for me – public IQueryable<Companies> GetCompanies(),I would get the full object with all columns.  So, I am going to build a custom class that only has company ID and name:

    public class ReadOnlyCompany

    {

        [Key]

        public int CompanyId { internal set; get; }

        public string CompanyName { internal set; get; }

    }

 

I am going to add this class to RIA Service project on .NET side (SilverlightRIAServicesLibrary.Web project in my case).  As you notice I did not have to decorate my class with DataContract attribute or decorate properties with DataMember attribute.  We do not actually need to do this, as RIA Services will take care of all that for us.  I do however need to use Key attribute or I would get a compile time error.  Each object is required to have a key (primary key) property.  Next step is to write a method in DomainService (RoldexDomainService in my case) class.  Here is what this would look like:

        public List<ReadOnlyCompany> GetReadOnlyCompanies()

        {

            return (from oneCompany in this.ObjectContext.Companies

                    orderby oneCompany.CompanyName

                    select new ReadOnlyCompany()

                    {

                        CompanyId = oneCompany.CompanyId,

                        CompanyName = oneCompany.CompanyName

                    }).ToList<ReadOnlyCompany>();

        }

 

Even though I return List object here, but RIA Services will actually return ReadOnlyObservableCollection<ReadOnlyCompany> on Silverlight side.  You have to remember that when you cast return value for RIA Services call to a specific object.  Here is what this call would look like on Silverlight side:

        private void GetCompaniesList()

        {

            ShowPleaseWaitMessage();

            var query = _context.GetReadOnlyCompaniesQuery();

 

            _context.Load<ReadOnlyCompany>(query, LoadBehavior.RefreshCurrent, (o) =>

            {

                HidePleaseWaitMessage();

                if (o.Error != null)

                    ErrorHandler.HandleException(o.Error);

                else

                {

                    this.Model = o.Entities as ReadOnlyObservableCollection<ReadOnlyCompany>;

                }

                    HidePleaseWaitMessage();

            }, null); ;

 

        }

Here I am putting up a please wait window, fire a query and interpret the results.  As I mention before, my next step is to get full Company object based on selected ID.  Again, I am adding a new method to DomainService class on .NET side:

        public Companies GetCompany(int companyID)

        {

            var returnValue = this.ObjectContext.Companies

                .Include("CompanyContacts")

                .Include("CompanyContacts.CompanyContactPhones")

                .Where(one => one.CompanyId == companyID).FirstOrDefault();

            return returnValue;

        }

Now, let’s see what this call looks like on Silverlight side.  This also demonstrates the use of parameters:

var companyQuery = _context.GetCompanyQuery(_companyID);

_context.Load<Companies>(companyQuery, (o1) =>

{

    HidePleaseWaitMessage();

    if (o.Error != null)

    {

        ErrorHandler.HandleException(o.Error);

    }

    else

    {

        this.Model = o1.Entities.First() as Companies;

    }

}, null);

As you can see, RIA services build us a query that already has the same company ID parameter for us.  Pretty cool!  However, if I look at return value (Companies object), I will notice that contacts property is actually null even though I did add .Include statement to my custom Entity Framework based method.  To get this to work, I have to modify the metadata class that RIA Services generated(RolodexDomainService.metadata.cs in my case).  I need to open this class file and look for Companies object.  I will find public EntityCollection<CompanyContactPhones> CompanyContactPhones property in it.  To get RIA Services to include child collection, I need to add Include attribute here as well:

[Include]

public EntityCollection<CompanyContactPhones> CompanyContactPhones;

I would have to take the same step to include phones collection for each contact.  If I run my code again, I will not get Company object with a list of Contacts, each containing a list of Phones.

I will try to cover update in my next post.

Thank you and do not hesitate to ask questions.

Talk at GGMUG

As always I had fun presenting at Gwinnett Georgia Microsoft Users Group on Thursday.  The subject of my talk was “Getting started with SQL Azure”.  I documented all the steps in this blog post.  There are also useful links that I mentioned in this post to help you get started.

There are many advantages to use SQL Azure.  Number of reason is probably the fact that one can eliminate the need to house expensive hardware and software on premises.  As long as you are fine with living with certain limitations of SQL Azure compared to SQL Server 2008, you can take advantage of this great technology.  The primary limitation is probably the size of the database.  You cannot have a database bigger than 10 GB.

Feel free to ask any questions on the topic.

AppFabric Caching (Velocity) and Versioning

To continue on the topic of Velocity, I will explore versioning today.

As I showed previously, you can use DataCache.Add method to add an item to cache.  This, of course, requires that this item’s key was not to be found in the cache already, or an exception will be thrown.  This puts a damper on versioning,  So, let’s look at a different method – Put.

You can use Put method to add/replace an item in cache.  If a key already exists, the item will be replaced, otherwise it will be added.

// add an item to cache

CachablePerson person1 = new CachablePerson();

person1.FirstName = "Version1";

DataCacheItemVersion version1 = _defaultCache.Put("personwithversion", person1);

 

 

Now, I will explore versioning of items.  In order to control versioning, I will use GetAndLock method to get an item from cache while locking it to ensure safe updates.  I will update a property of an object I got from cache, then I will put it back into cache.

// get an item and lock it

DataCacheLockHandle handle;

CachablePerson temp = _defaultCache.GetAndLock("personwithversion", TimeSpan.FromSeconds(1), out handle, true) as CachablePerson;

/update an item

temp.FirstName = "Version2";

//put it back and get the new version

DataCacheItemVersion version2 = _defaultCache.PutAndUnlock("personwithversion", temp, handle);

Now I will version that versioning actually works by getting both initial and new items

// get initial item

CachablePerson ver1 = (CachablePerson)_defaultCache.Get("personwithversion");

// get the item with version 2

CachablePerson ver2 = (CachablePerson)_defaultCache.GetIfNewer("personwithversion", ref version1);

To proof that the process worked, I will output the results to a window or console.  In my case ver1.FirstName is Version1 and ver2.FirstName is Version2 which is what is expected.

In this post I looked at the Put method that makes it easier to put items into cache without worrying if an item with the same key already exists.  I also looked at the way to maintain many versioned items with the same key in cache in case versioning is important to the consuming application.

You can download the updated initial sample here.

Getting Started with Velocity (AppFabric Caching Library)

I have worked through my first Velocity project today, and I would like to blog about  the steps necessary to use caching.

First, you should read my previous post and install AppFabric on your machine.

I used Visual Studio 2010 beta 2 to create the solution.  You can download the solution here.  I create WPF project in order to prove that caching is not limited to web applications, although web farm would probably be an ideal application for caching.  Once project is created, I added references to DLLs for Velocity.  On my machine they were located in C:\Windows\System32\ApplicationServerExtensions.  Two DLLs I needed were CacheBaseLibrary.dll and  ClientLibrary.dll.  They contain key classes that can be used to utilize caching.  I could not add them directly from that folder, I was getting an error from Add Reference dialog.  So, I copied them into a folder under my Solution (“Bin” folder).

Then I added a complex class that I intended to cache.  I wanted to prove to myself that complex object graphs are OK since all the demos I saw just used strings.  Here is the class I used:

 

    public class CachablePerson

    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public List<CachableAddress> Addresses { get; set; }

        public CachablePerson()

        {

            FirstName = "Sergey";

            LastName = "Barskiy";

            Addresses = new List<CachableAddress>();

            Addresses.Add(new CachableAddress() { Street = "Main Street", City = "Atlanta" });

            Addresses.Add(new CachableAddress() { Street = "Second Street", City = "Lilburn" });

        }

    }

 

    public class CachableAddress

    {

        public string Street { get; set; }

        public string City { get; set; }

    }

 

I put the class into its own project and referenced this project from two separate WPF application projects.

First step in using caching is to configure cache object.  Here is how we can configure cache object using cache factory:

        private void SetupCache()

        {

            DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];

            servers[0] = new DataCacheServerEndpoint("Sergey-Laptop", 22233, "DistributedCacheService");

            _cacheFactory = new DataCacheFactory(servers, false, true);

            _defaultCache = _cacheFactory.GetCache("default");

        }

 

Now we are ready to add object to cache.  We will do this in steps.  First we check to see if an object is already in cache, and if so, we will remove it from cache.  Cache basically is using a string as the object key.  In addition to that you can also version objects, thus having multiple copies of the same object with the same key existing in cache at any given time.

            if (_defaultCache.Get("person") != null)

            {

                _defaultCache.Remove("person");

            }

            _defaultCache.Add("person", _person);

 

 

Now I am going to get the object from cache.  Just as simple as adding it:

_person = (CachablePerson)_defaultCache.Get("person");

 

Simple and easy.  I think Velocity is super powerful yet simple to use.  Event though it would be an abuse, but one could possibly use caching to communicate between different applications. 

You can download my sample solution here

Windows AppFabric and Velocity

I downloaded Windows AppFabric Beta 1 version this week.  You can find this download here. It took a few hours to install it.  I could surely tell I was dealing with beta 1 of version 1 of the product.  I finally installed it using new cluster option and XML configuration option.  I tried SQL Server configuration  option a few times, but it never installed without errors.  I think at the end I ran the install about a dozen times before it succeeded.

Anyway, three hours later or so I was done.  Next I tried to run a downloaded sample.   No matter what I tried, I could not get the sample to work.  It looked pretty obvious that I still need to configure something.  Finally after another 30 minutes I found an answer – I had to start the cache cluster.  To do so, I went to Programs –> Microsoft Distributed Cache –> Administration tool.  I was sort of surprised that this launched PowerShell window.  I guess we need to wait until release to get real nice configuration software with GUI.  In the mean time, I had to type “start-cachecluster”.  Once I ran that and saw that the server was started, I went back to run the samples.  They worked perfectly well this time.

Once I write my own sample, I will post source code on this blog.

Windows Azure Application

This is purely a bragging post :-)

I just deployed a test application to the cloud (Microsoft Azure): http://rolodex.cloudapp.net/

Here is the technology stack for it:

  1. Windows Azure
  2. SQL Azure
  3. CSLA 3.8.1
  4. Silverlight
  5. Entity Framework
  6. WCF
  7. Prism (Composite Application Guidance)
  8. Silverlight Toolkit

I promise to write a blog entry in the near future, the steps one has to follow through to create an Azure application.

Getting Started with SQL Azure

I setup an account with SQL Azure last week, and I would like to document each step I took in order. 

There is a lot of information on SQL Azure FAQ and Zack Owens’ blog.  I still ran into some issues though, and I wanted to provide detailed instruction on how to work through them.

Step 1 – Get SQL Azure token.  You need to Microsoft Azure site and scroll down the page to request tokens.

Step 2 – Wait for the email you will receive that will contain the token (invitation code) and instructions on how to activate it. Follow those step to setup an account.

Step 3 – Create new project in SQL Azure.  You will setup user ID and password as part of that process.

Step 4 – Create a database with a name you choose and setup firewall

image

 

image 

 

image

You can see your own IP address on this window above as well.  You can just copy that address and paste it into both IP ranges – low and high,

Step 5 – Start SSMS (SQL Server Management Studio).  Hit Cancel on initial login screen.

image

Step 6 – Click New Query button

image

Step 7 – Enter your server information, but do NOT click Connect

image

Step 8 – Click Options and enter your database name

image

Step 9 – Click “Connect”.  You should not get any errors and now you can see a query window.  You are ready to add tables.

Step 10 – Type in script to create database structure.  Important: not all standard SQL commands are supported.  If you are scripting an existing database, you will need to remove all file group references, such as “ON PRIMARY”. 

image

Step 11 – Create a standard .NET application.  You can get exact connection string on your SQL Azure management page:

image

You are done!

Find more information on SQL Azure FAQ and Zack Owens’ blog.

Entity Framework 4.0 CTP

I just installed CTP of entity framework 4.0 (2.0 technically).  I decided to test the most advertized feature – ability to have actual foreign keys (IDs) in addition to navigation properties.  The lack of this feature has been the biggest annoyance for me while working with Entity Framework for many months now.

Here is the model I created

image

As you can see Companies have Contacts, and each contact object now has CompanyID in addition to Company navigation property.  I had to select this option while generating the model from the database.  The checkbox for option to include foreign key values was available on one of the wizard screens.

Here is the code I wrote for testing:

 

            using (RolodexEntities context = new RolodexEntities())

            {

                CompanyContact newConact = new CompanyContact();

                newConact.CompanyId = 2;

                newConact.BaseSalary = 1;

                newConact.Birthday = DateTime.Today;

                newConact.FirstName = "Sergey";

                newConact.LastName = "Barskiy";

                newConact.RankId = 1;

                context.AddToCompanyContacts(newConact);

                context.SaveChanges();

            }

Hurray!  It worked!  New contact was added to the database and linked to Company with ID of 2 and Rank with ID of 1.

This feature to me is invaluable in n-Tier development when a developer has to replay the changes on the server after allowing the user to edit the data on the client.  Now, we can just transmit all properties of a Contact to the server, (probably with IsNew, IsUpdated, IsDeleted flags), set the foreign keys via IDs, then save.

Silverlight And N-Tier Data Access using Entity Framework

As I mentioned before I talked at GGMUG last Thursday.  I talked about Entity Framework in general and specifically in N-Tier applications, such as Silverlight applications.  I think I got a few folks excited about using Entity Framework.  The key thing to remember when using EF in N-Tier applications is that EF keeps track of changes in the context object.  Unfortunately, this object does not survive the trips between client and the server.  As a result, my recommendation is to use EF in conjunction with a business layer framework, such as CSLA. You can download slides and sample project here.  Please feel free to post comments or questions.

I will be talking at GGMUG on Thursday, September 10th

I will be presenting at the next Gwinnett Georgia Microsoft Users Group this coming Thursday.  The topic of my presentation will be Entity Framework in general and its applications to Silverlight development.  I will be posting the zip file with slides and sample application immediately after the presentation.

I hope to see you there!

Entity Framework and multiple relationships between two tables

Here is a scenario – I have two tables – Users and Phones.  Users table has two columns that relate to Phones table – PrimaryPhone and SecondaryPhone.  If you build an EF model with these two tables, you will end up with Users entity with two navigation properties that relate to Phones entity – Phones and Phones1.  Yes, I hope this excellent :-( naming convention will be fixed in EF 2.0.  Our goal – retrieve the data for both phones with each user.  If you do the following:

var query = (from oneUser in Users.Include(“Phones”)

you will end up with only secondary (or primary) navigation property in Users object populated.  So, either Users.Phones or Users.Phones1 will have data, the other one will be null.  Important thing to realize when working with Entity Framework is that “.Includes”  statement works off navigation property names, not table names.  So, if you would like to populate both primary and secondary phone, you need to use the following query:

var query = (from oneUser in Users.Include(“Phones”).Include(“Phones1”)

Using Entity Framework as Data Access Layer in n-Tier applications

I have been using Entity framework as DAL for a CSLA for Silverlight based application.  I have player a role in uncovering a number of issues that make it very hard to use in these circumstances.  Here is my (surely incomplete) list.

1. Foreign keys handling.  The actual IDs that are used as foreign keys are not built as properties when you generate a model from a database.  Instead you get navigation properties.  For example, you have User and UserTypes table.  Users table has UserTypeID in it.  When you build a mode for this, you will have UserTypes property in Users entity, but not access to UserTypeID.  As a result, when you are rehydrating a users object in n-Tier environment, you have to have an instance of UserTypes entity to attach a user to.  Your options are to retrieve it from database (inefficient) or write a helper class that creates one on the fly.  To do so, you create an instance of UserTypes entity, then set entity key on it, then attach it to context.  To do all this, you will need to know ID in advance.  You can do this by using UserTypesReference property in Users entity – it will contain UserTypesID when you retrieve an instance of Users from DB.  You can store it in a property of the user object (CSLA for example) that you will use in UI.

2.  Another foreign key annoyance is an instance when you have multiple columns from one table relating to another table.  For example, Users table has columns PrimaryType and SecondaryType, both relating to UseTypes table.  As a result you will get navigation properties UserTypes1 and UserTypes2 in Users entity.  This is pretty much useless because as you write code against that, you will need to constantly have your model open to figure out what ID you need to use.  On top of that, if you use .Include(“UserTypes”) syntax to get the user with both primary and secondary columns, only one of the UserTypes properties will be populated with an instance of UserTypes if you have different IDs in property and secondary columns.  What do you do then?  Your only option is to use UserTypes1(2)Reference property to either get an ID or retrieve an instance of UserTypes table

3.  Third foreign key issue is concurrency handling.  Typically, for all properties you can indicate if a column is to participate in concurrency handling.  For some reason, you cannot do the same for navigation properties – they always participate in concurrency handling if they are changing.  As a result, you have to always keep track of old and new value for each navigation property,  You would set its old value before attaching it to the context, then set it to the new value.  If you capture the SQL query that is sent to the DB when the values are not the same, you will find navigation properties are part of the where clause / concurrency checking.  Sad but true.

4.  Re-using context for Oracle and SQL server (or any multiple databases).  Currently Microsoft ships entity framework only with SQL Server provider.  So, you are stuck buying some third party Oracle provider and hope that the model it generates will be the same as SQL server model, so that you only need to change connection string when switching databases.  There is a promise we might get there one day, but today is not that day.

Linq to SQL

I just read this blog post on ADO.NET team blog.  I have been wondering about the future on Linq to SQL since the release of Entity Framework.  There is signification overlap in capabilities of both technologies, and one must wonder about the overhead Microsoft is willing to incur in maintaining both.  My guess is, they will not do this forever.  So, if you are starting a new application, would you use Linq to SQL today.  My answer is no.