Blog Home  Home Feed your aggregator (RSS 2.0)  
A Random Walk Around .Net - Friday, May 02, 2008
 
 Monday, April 28, 2008

            I am sure I have said this before; has anyone else noticed how little code I have written?  I have quite a bit to talk about, so tonight I will just drop all my code and screen shots unaccompanied.  Thereafter, we will spend the next few evening talking about exactly what was done.

First, I created the data contracts.

 

Second, I created the service contracts.

 

Third, I added a Silverlight browser project.

 

Fourth, I added the WPF XAML for the Silverlight front end.

 

<UserControl x:Class="DBinsor.Svc.WCF.Browser.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:grid ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
    <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="10" />
            <RowDefinition Height="90" />
            <RowDefinition Height="50*" />
            <RowDefinition Height="50*" />
            <RowDefinition Height="10" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10" />
            <ColumnDefinition Width="50*" />
            <ColumnDefinition Width="50*" />
            <ColumnDefinition Width="10" />
        </Grid.ColumnDefinitions>
        <grid:DataGrid x:Name="CastleGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="1" Grid.Column="2" 
                       MouseLeftButtonDown="CastleGrid_MouseLeftButtonDown" />
        <grid:DataGrid x:Name="ContractGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="1" Grid.Column="1" 
                       MouseLeftButtonDown="ContractGrid_MouseLeftButtonDown"/>
        <grid:DataGrid x:Name="ComponentGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="2" Grid.Column="2" 
                       MouseLeftButtonDown="ComponentGrid_MouseLeftButtonDown" />
        <grid:DataGrid x:Name="ImplementationGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="2" Grid.Column="1" />
        <grid:DataGrid x:Name="ComponentParametersGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="3" Grid.Column="2" 
                       CanUserResizeColumns="True" />
        <grid:DataGrid x:Name="ContractParametersGrid" AlternatingRowBackground="Beige" 
                       AutoGenerateColumns="True" Grid.Row="3" Grid.Column="1" 
                       CanUserResizeColumns="True" />
    </Grid>
</UserControl>

Fifth, I hooked the WCF Service to the Silverlight browser.

 

using System;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;
using DBinsor.Svc.WCF.Browser.DatabaseProxy;

namespace DBinsor.Svc.WCF.Browser
{
    public partial class Page : UserControl
    {
        DatabaseServiceContractClient _dscc;
        Castle _selectedCastle;
        Contract _selectedContract;
        Component _selectedComponent;

        public Page()
        {
            InitializeComponent();
            this._dscc = new DatabaseServiceContractClient();
            this._dscc.DemandCastlesCompleted 
                += new EventHandler<DemandCastlesCompletedEventArgs>(_dscc_DemandCastlesCompleted);
            this._dscc.DemandComponentParametersCompleted
                += new EventHandler<DemandComponentParametersCompletedEventArgs>(_dscc_DemandComponentParametersCompleted);
            this._dscc.DemandComponentsCompleted
                += new EventHandler<DemandComponentsCompletedEventArgs>(_dscc_DemandComponentsCompleted);
            this._dscc.DemandContractParametersCompleted
                += new EventHandler<DemandContractParametersCompletedEventArgs>(_dscc_DemandContractParametersCompleted);
            this._dscc.DemandContractsCompleted
                += new EventHandler<DemandContractsCompletedEventArgs>(_dscc_DemandContractsCompleted);
            this._dscc.DemandImplementationsCompleted
                += new EventHandler<DemandImplementationsCompletedEventArgs>(_dscc_DemandImplementationsCompleted);

            LoadPrimaryTables();
        }

        private void LoadPrimaryTables()
        {
            this._dscc.DemandCastlesAsync();
            this._dscc.DemandContractsAsync();
        }

        private void _dscc_DemandCastlesCompleted(object sender, DemandCastlesCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.CastleGrid.ItemsSource = e.Result;
        }       
        
        private void _dscc_DemandComponentParametersCompleted(object sender, DemandComponentParametersCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.ComponentParametersGrid.ItemsSource = e.Result;
        }
        
        private void _dscc_DemandComponentsCompleted(object sender, DemandComponentsCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.ComponentGrid.ItemsSource = e.Result;
        }

        private void _dscc_DemandContractParametersCompleted(object sender, DemandContractParametersCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.ContractParametersGrid.ItemsSource = e.Result;
        }

        private void _dscc_DemandContractsCompleted(object sender, DemandContractsCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.ContractGrid.ItemsSource = e.Result;
        }

        private void _dscc_DemandImplementationsCompleted(object sender, DemandImplementationsCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HtmlPage.Window.Alert(e.Error.Message);
                return;
            }

            if (e.Result.Count == 0)
            {
                return;
            }

            this.ImplementationGrid.ItemsSource = e.Result;
        }

        private void CastleGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            object temp = CastleGrid.SelectedItem;

            if (temp == null)
            {
                return;
            }

            this._selectedCastle = temp as Castle;

            this._dscc.DemandComponentsAsync(this._selectedCastle);
        }

        private void ContractGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            object temp = ContractGrid.SelectedItem;

            if (temp == null)
            {
                return;
            }

            this._selectedContract = temp as Contract;

            this._dscc.DemandImplementationsAsync(this._selectedContract);
            this._dscc.DemandContractParametersAsync(this._selectedContract);
        }

        private void ComponentGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            object temp = ComponentGrid.SelectedItem;

            if (temp == null)
            {
                return;
            }

            this._selectedComponent = temp as Component;

            this._dscc.DemandComponentParametersAsync(this._selectedComponent);
        }
    }
}

Sixth, I used LINQ to Extract Data from the Entity Framework.

 

using System.Linq;


namespace DBinsor.Svc.WCF.BusinessLogic
{
    public static class DatabaseToDataContractGenerator
    {
        public static DataContracts.Castles GetCastles()
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                DataContracts.Castles ret = new DataContracts.Castles();
                var dataCastles = from castle in
                                      db.Castle
                                  select castle;

                foreach (DataAccess.Model.Castle dataCastle in dataCastles)
                {
                    DataContracts.Castle serviceCastle =
                        new DataContracts.Castle();
                    serviceCastle.id = dataCastle.Id;
                    serviceCastle.name = dataCastle.Name;
                    ret.Add(serviceCastle);
                }

                return ret;
            }
        }

        public static DataContracts.Components GetComponents(DataContracts.Castle castle)
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                int temp;
                DataContracts.Components ret = new DataContracts.Components();
                var dataComponents = from component in
                                         db.Components
                                     where component.Castle.Id == castle.id
                                     select component;

                foreach (DataAccess.Model.Components dataComponent in dataComponents)
                {
                    DataContracts.Component serviceComponent =
                        new DataContracts.Component();
                    serviceComponent.id = dataComponent.Id;
          
                    int.TryParse(dataComponent.InitialPoolSize.ToString(), out temp);
                    serviceComponent.initialPoolSize = temp;
                    serviceComponent.inspectionBehavior = dataComponent.InspectionBehavior;
                    serviceComponent.lifestyle = dataComponent.Lifestyle;
                    int.TryParse(dataComponent.MaxPoolSize.ToString(), out temp);
                    serviceComponent.maxPoolSize = temp;
                    serviceComponent.Castle = castle;
                    serviceComponent.Implementation = new DataContracts.Implementation();
                    //todo: Add Implementation Name
                    ret.Add(serviceComponent);
                }

                return ret;
            }
        }

        public static DataContracts.ComponentParameters GetComponentParameters(DataContracts.Component component)
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                DataContracts.ComponentParameters ret = new DataContracts.ComponentParameters();

                var dataComponentParameters = from componentParameter in
                                                 db.ComponentParameters
                                             where componentParameter.Components.Id == component.id
                                             select componentParameter;

                foreach (DataAccess.Model.ComponentParameters dataComponentParameter in dataComponentParameters)
                {
                    DataContracts.ComponentParameter serviceComponentParameter =
                        new DataContracts.ComponentParameter();
                    serviceComponentParameter.Component = component;
                    serviceComponentParameter.overrideValue = dataComponentParameter.OverrideValue;
                    //todo: Add Contract Parameter Name
                    ret.Add(serviceComponentParameter);
                }

                return ret;
            }
        }


        public static DataContracts.Contracts GetContracts()
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                DataContracts.Contracts ret = new DataContracts.Contracts();
                var dataContracts = from contract in
                                      db.Contracts
                                  select contract;

                foreach (DataAccess.Model.Contracts dataContract in dataContracts)
                {
                    DataContracts.Contract serviceContract =
                        new DataContracts.Contract();
                    serviceContract.id = dataContract.Id;
                    serviceContract.contractNamespace = dataContract.Namespace;
                    serviceContract.contractInterface = dataContract.Interface;
                    ret.Add(serviceContract);
                }

                return ret;
            }
        }

        public static DataContracts.Implementations GetImplementations(DataContracts.Contract contract)
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                DataContracts.Implementations ret = new DataContracts.Implementations();

                var dataImplementations = from implementation in
                                              db.Implementations
                                          where implementation.Contracts.Id == contract.id
                                          select implementation;

                foreach (DataAccess.Model.Implementations dataImplementation in dataImplementations)
                {
                    DataContracts.Implementation serviceImplementation =
                        new DataContracts.Implementation();
                    serviceImplementation.name = dataImplementation.Name;
                    serviceImplementation.Contract = contract;
                    ret.Add(serviceImplementation);
                }

                return ret;
            }
        }

        public static DataContracts.ContractParameters GetContractParameters(DataContracts.Contract contract)
        {
            using (DataAccess.Model.Entities db =
                   new DataAccess.Model.Entities())
            {
                DataContracts.ContractParameters ret = new DataContracts.ContractParameters();

                var dataContractParameters = from contractParameter in
                                              db.ContractParameters
                                          where contractParameter.Contracts.Id == contract.id
                                          select contractParameter;

                foreach (DataAccess.Model.ContractParameters dataContractParameter in dataContractParameters)
                {
                    DataContracts.ContractParameter serviceContractParameter =
                        new DataContracts.ContractParameter();
                    serviceContractParameter.name = dataContractParameter.Name;
                    serviceContractParameter.defaultValue = dataContractParameter.DefaultValue;
                    serviceContractParameter.Contract = contract;
                    ret.Add(serviceContractParameter);
                }

                return ret;
            }
        }

    }
}

Seventh, I had to add the CSDL, MSL and SSDL files to my host project to make things work.  Still need to think about a better way to do this:

 

  

<connectionStrings>
     <add name="DBinsor.Svc.WCF.DataAccess.Properties.Settings.WindsorDataBaseConnectionString"
         connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\WindsorDataBase.mdf;Integrated Security=True;User Instance=True"
         providerName="System.Data.SqlClient" />
 </connectionStrings>

Finally, Here is the End Product:

Monday, April 28, 2008 8:55:50 PM (Central Standard Time, UTC-06:00)  #    Comments [0]    | 
 Sunday, April 27, 2008

            Both of these technologies are very powerful ways of implementing object to relational mapping.  With LINQ to SQL, I feel it should be built on top of “views” so when one makes table changes the whole system doesn’t come crashing down.  The Entity Framework seems to cover such scenarios in its mapping functionality.

            However, neither seems to place nice in the n-tier model.  That is, in which DLL should the EDMX or the DBML files belong?  In one sense they do data access and in another they define business entities.  On the one hand, I suppose one could put them in the data access layer and use business logic to convert those entities to ones defined in the business tier.  Yet, that seems like a lot of work and bit un-refactored.  On the other hand, we could put them in the business layer, but then we are doing data access from the business layer.

            I would like to see a system where the data access is decoupled from the entities.  For now, I am going to add these files to the data access layer.  Furthermore, I am going to add the Data Contracts from my service layer to my business layer: not really happy about that.  However, this will allow me the ability to use my business layer as a translator to expose my entities to the Silverlight frontend.

            I could add the data access to my service implementation project, but I think it is better to do such translations in the business layer.  Obviously, we could build duplicate entities in the business layer and translate twice, then again to much work and not that refactored.

Sunday, April 27, 2008 7:00:28 PM (Central Standard Time, UTC-06:00)  #    Comments [0]    | 
 Saturday, April 26, 2008

I am using Windows XP Professional, Visual Studio 2008 Professional, IE 7.0 and Silverlight 2.0.  The weird thing is I must delete my history every time in IE before I can view changes to my Silverlight application.  I am assuming that is caching the XAP file in the browser and not reloading it when I make changes.  I am sure there is a work around, but I have not had time to look for it.  Any ideas?

Saturday, April 26, 2008 6:33:42 PM (Central Standard Time, UTC-06:00)  #    Comments [0]    | 
 Friday, April 25, 2008

It has been a couple weeks since my last post.  As with many juggling family, career, socializing and hobbies can be quite a circus act.  Nonetheless, the DBinsor solution has not yet reached a critical mass for usability.

It is great that one can pull the configuration from the database, but how does one put it there in the first place.  Moreover, this process of insertion should be intuitive as well as allow for a holistic view of the data.

The end user of choice for DBinsor would be a system which utilized a plug in methodology meshed with a SOA topology.  More specifically, one who utilizes services contracts where the implementation is defined by configuration settings.  Thus utilizing DBinsor as a centralized configuration store should be quite appealing.

With this type of user in mind, a web user interface is the only sensible approach.  For example, an administrator could seamlessly change configurations of any service from any computer with accessibility to the DBinsor server without installing a windows client.

We could have chosen web forms or the new model view controller framework; however Silverlight 2.0 seems the most intriguing.  Moreover, we get the chance to work with XAML instead of HTML and Java Script.  The “Learn” section has been quite helpful in the process of learning Silverlight.

We will post something once we have basic functionality working.

Friday, April 25, 2008 5:15:16 PM (Central Standard Time, UTC-06:00)  #    Comments [0]    | 
 Sunday, April 13, 2008

            We uploaded the working code to the Code Gallery Site.  This should allow readers of this blog the ability to see exactly what is happening underneath the hood.  One very interesting use of this application is a centralized configuration repository.  That is because of the parameters feature of the Windsor Library, a user should use those instead of a configuration file.

If anyone is interested in contributing to this project, please send me an email.  The next features will include:

·         A web GUI to access the database

·         A windows application using reflection to auto generate data from an assembly

·         Using card space to add security

·         Exposing all the features of the container.

·         Performance Enhancements

·         And others.

We have also added Code Gallery to Navigation Section.

Sunday, April 13, 2008 6:07:53 PM (Central Standard Time, UTC-06:00)  #    Comments [0]    | 
 Saturday, April 12, 2008

To test this, we decided to setup an interface and two derived classes.  Then we added corresponding data to the database (we will build an intuitive graphical user interface eventually).  Finally, we used the Container Singleton class to resolve our types and print out the results.

 

            Class Diagram:

Database:

 

            Windsor Component View

Lookup Name

Namespace

Contract

Implementation

Component Id

Contract Id

Test1

DBinsor.Svc.WCF.Client

IMath

Add

1844d2e0-455e-4d44-a9ff-1c63f78e407b

0aa71152-91d4-4e8f-a4a0-4124a98e2851

Test1

DBinsor.Svc.WCF.Client

IMath

Subtract

5c3ee79a-926c-4438-8391-44a437bd8f47

0aa71152-91d4-4e8f-a4a0-4124a98e2851

           

            Windsor Parameters View

Component Id

Contract Id

Parm Name

Default

Override

5c3ee79a-926c-4438-8391-44a437bd8f47

0aa71152-91d4-4e8f-a4a0-4124a98e2851

a

1

13

5c3ee79a-926c-4438-8391-44a437bd8f47

0aa71152-91d4-4e8f-a4a0-4124a98e2851

b

2

NULL

1844d2e0-455e-4d44-a9ff-1c63f78e407b

0aa71152-91d4-4e8f-a4a0-4124a98e2851

a

1

NULL

1844d2e0-455e-4d44-a9ff-1c63f78e407b

0aa71152-91d4-4e8f-a4a0-4124a98e2851

b

2

NULL

 

            Classes:

 

            Test:

IMath proxy = ContainerSingleton.Instance.Resolve<Add, IMath>();

Console.WriteLine(proxy.Calculate().ToString());

 

proxy = ContainerSingleton.Instance.Resolve<Subtract, IMath>();

Console.WriteLine(proxy.Calculate().ToString());

 

Console.WriteLine(ContainerSingleton.Instance.Xml);

           

            Result:

3