Skip to main content

I hear C#, I see C#, I do .NET

Go Search
Home
  

I hear C#, I see C#, I do .NET > Categories
LINQ in a Multi-Tiered Architecture

Do you feel that whenever there is some change in tools and options on how we develop solutions we struggle to figure out how this new thingamajig play with already proven approaches? LINQ is no exception. Often asked question is will LINQ play nice with multi-tiered architecture? If you check MSDN LINQ forum this is probably one of ten questions asked over and over again…

After working a while with the LINQ I have to keep reminding myself that it is what it says it is: Language Integrated Query. Adding to the general population confusion is LINQ-to-SQL. LINQ-to-SQL is ORM mapper to map .NET Entities to SQL Entities and transform LINQ(uery) to TSQL.

I am going to describe how I perceive the logical multi-tier architecture (MTA). The image below is what I imagine when I speak of MTA.

image

Let me describe this diagram... Two logical (emphasis on logical) tiers A and B are hosting boundary to Services and Consumers. Between these tiers there is some kind of message transfer Medium through which Messages travel. Little lollypop shape represents Endpoints from which messages are sent and/or received.

Although, both tiers are depicted inside the Host boundaries this is not necessary but I feel that provides completes the MTA picture in my head.

In the next example I can demonstrate factoring of this concept in the concrete implementation.

image

Ok this is VERY simple example of factoring of the logical design. I have highlighted elements that are easily recognizable from the MTA model. Also, until we run this project this would be a static representation of the model.

One thing that is noticeably missing is the Medium. Medium is not present because it does not exist until we run the Host and create an instance of the model in the host. There is a lot going behind the scenes to get this going but just imagine that our Host is created and running. The Medium we are using to exchange messages in this particular implementation is memory! Without going into way to much detail bits and bytes representing our message is being moved around the computer memory and they arrive to their destination with help of the OS and its services.

This simple example is devoid of all the complications that begin to arise when you start factoring the components into different files, assemblies, process and computers but it demonstrates the basic concepts on how I see things working (maybe to simple?).

If you have not noticed I am true believer that each component, and according to Juval Löwy from IDesgin, each class (he has some very cool stuff for running class as service), is a service to which you send  and receive messages from.

So, LINQ, where does it fit in?

I use these as my general guiding principles when it comes to LINQ and MTA:

  1. To communicate between layers use WCF.
  2. Use SQLMetal.exe to decorate your classes with DataContract attribute.
  3. Do not chain queries across boundaries - it is tempting to create one query than send it off (as message == Expressions) to another part of your app or tier for either processing or further specialization.
  4. You should encapsulate your LINQ into reusable components and expose it as services to the consumers
  5. When using LINQ-to-SQL don't operate on data context outside your data tier
  6. Avoid using LINQ-to-SQL directly, use EntityFramework instead.

Some of the above principles apply to general application design and are nothing new.

In conclusion I think that we should strive to keep the model indifferent to forces and challenges imposed by use of LINQ in our projects.

image

I would like to hear your opinions where and how LINQ fits in MTA or your project!

Petar

Multi-field foreign key relationship to the same database table and LINQ

Huh! What a title... Let me explain... It is somewhat standard practice to have table with multiple columns that are referring to the same entity in the database. For example, CreatedByUserID and ChangedByUserID in some table are both referring to the User table UserID primary key. So, how does this work with LINQ?

Here is the sample DDL used in my examples:

create table Issues 
(IssueID int IDENTITY PRIMARY KEY, Description nvarchar(100), ChangedByUserID int, CreatedByUserID int)
create table Users 
(UserID int IDENTITY PRIMARY KEY, UserName nvarchar(100))
alter table Issues add CONSTRAINT FK_ChangedBYUserID 
    FOREIGN KEY (ChangedByUserID) REFERENCES Users(UserID)
alter table Issues add CONSTRAINT FK_CreatedByUserID 
    FOREIGN KEY (CreatedByUserID) REFERENCES Users(UserID)

If you would to drag the tables from Server Explorer on to the Visual Studio DBML design surface it would look something like picture below. Two columns e.g. CreatedUserID and ChangedUserID both have a foreign key reference to a single User table in the database hence the two arrow lines pointing towards the Issue table.

image

 

image

If you were to peak inside the auto generated file you will find that designer has done its best and created two properties on Issue entity with names of User and User1.

 

 

 

 

 

imageSimilarly, it created two properties on User entity with names of Issue and Issue1 respectively.

 

 

 

 

 

 

Well this is pretty much useless when it comes to understanding this model. What is User1 or Issue1?

There are couple of ways handling this problem. First, you could restructure your database and differentiate between user kind and second we could tweak the generated code and make our life easier. Big drawback with a second approach is that you would have to do this every time if you re-generate DBML! Although first approach might be better sometimes its not feasible.

In case that you are not auto-generating the DBML here is how you can make this little bit better.

First remove one of the relationships and than rename the entity to the remaining relationship like so:

image

The association editor opens up when you double-click the black diamond arrow.

Now this gives us better syntax:

image

To get the other field (CreatedBy) bound to a table in the DBML designer drop the User table again from the Server Explorer and rename it immediately (even before saving) to the other field entity name. Finally, remove the opposite relationship. Diagram should look something like this:

image

One more FINAL thing :) Open the properties of the relationship (the arrow) between the last table and expand Child Property. Remove the number from the name (in my case it was Issue1).

image

 

Now we get something that makes more sense in this model when trying to write LINQ from both directions...

image

image

I am not sure this is really ideal solution but VS should be supporting this kind of scenario out-of-the-box. Let me know if you have found a better way of making this work!

Petar

Get your LINQ in sync inside IDE - low tech

Visual Studio IDE support for keeping up your LINQ-To-SQL entities in sync with the database is weak. I have this low tech solution that can keep your database and your IDE in sync. The task looks bit daunting at first but at the end you are two clicks away from re-generating your LINQ-To-SQL entities. Here are the steps to setup the LINQ sync...

First create CMD file that contains the SQLMetal.exe with instructions for creating your database and add it to your project.

image

My CMD file is called LINQ_RegenerateDB.cmd. The extension CMD gives you a hint that we will execute this file with the cmd.exe. The  content of the this file is this command:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SqlMetal.exe" /conn:"Server=.;Database=Northwind;Integrated Security=SSPI;" /dbml:NorthWind.dbml /context:NorthwindDataContext /pluralize /serialization:Unidirectional
/namespace:DataServices /language:C# /views /functions /sprocs

  • /conn - is the connection string to your database
  • /dbml - creates the .DBML file
  • /context - is the name you would give to your class deriving from DataContext
  • /pluralize - I like my object names plural
  • /serialization - specifying the keyword Unidirectional  adds the [DataContract()] attribute on top of every entity
  • /namespace - puts the generated classes into namespace of your choice
  • /language - directs the custom build tool to use C# syntax
  • /views + /functions + /sprocs - instructs SQLMetal to create views, functions and stored procedure wrappers

To execute the .CMD file from IDE go to Tools/External tools and add new external tool CMD like I have in the picture below. Check "Use Output window" so you can monitor when the SQLMetal is finished running in the Output window of the IDE.

image

To re-generate your DBML file select the .CMD file in your project and on the Tools menu find the CMD menu item. Clicking on the CMD menu item will invoke CMD.EXE and in turn invoke SQLMetal.exe with specifications for re-generating your entire database. I have not found the way to limit what is being generated just yet.

 image

DML file is not in your project just yet so add it from the project folder. Next time you run the cmd.exe IDE will detect the change and ask you to reload if you have the DBML file already open. Click Yes when you see the dialog below.

image

Every time you regenerate your DBML file all the entities will be stuck in the top left corner. Right click anywhere in the white space and select Layout Diagram to let IDE reposition all the squares around.

Next to last step is to run the Custom Tool to create .CS file with actual entity implementation. To do this right click the DBML file and select Run Custom Tool.

image

When the custom tool generates the code file it omits one of the constructors. I have created new file with partial class for my data context (Northwind.usercode.cs) and added this constructor my self. This constructor passes the connection string found in your app.config via Settings type.

namespace DataServices
{
    public partial class NorthwindDataContext
    {
        public NorthwindDataContext() : 
                base(global::Model.Properties.Settings.Default.NorthwindConnectionString, mappingSource)
        {
            OnCreated();
        }
    }
}

image 

The final step is to add the NorthwindConnectionString settings. Right click your project and select Properties. On the Setting tab add new row with NorthwindConnectionString like on the picture below.

image

 

Next time you only need to run the CMD from your Tools menu and Run Custom Tool. Rest of the settings will be retained.

If someone has found a better way please let me know.

Petar.

Why we (not?)need to use LINQ

LINQ is here to stay. I am using it every day, my colleagues are using it, our clients are using it.

I wanted to see what others developers are doing with LINQ or what kind of issues are they confronted with using it in their development efforts. I turned to the user MSDN LINQ forum which has great moderators (bunch from Microsoft) as well as quite a few knowledgeable people answering a wide variety of questions.

One of the post had few questions (shortened a bit) I found interesting: "Why do we need to use LINQ? If we use it we don't need to write stored procedures? What is the advantage of using LINQ?". I would like to take try answering these ...

Why do we need to use LINQ?

LINQ - Language Integrated Query, meaning ability to write queries that transcend particular storage technology (memory- LINQ to objects, TSQL - LINQ-to-SQL) allows cleaner separation of concerns between writing a query and executing a query. So the why, to me, would be aimed at these design attributes: usability, reusability, portability, robustness and maintainability. I think the why not attributes would be efficiency, testability and interoperability (see the post about System Quality Attributes).

Is LINQ enterprise ready? It depends how you use it. If you can keep your data model simple you will get best bang for the buck otherwise I think you might be headed for trouble until Entity Framework.

If we use it (LINQ) we don't need to write stored procedures?

Stored procedure (server side code) is a good choice when needing to encapsulate some of the set based operations that involve business logic operating on medium to large number of rows and do not want to transmit this data to the client for processing. Stored procedures are very cumbersome for the simple CRUD scenarios and I tend to avoid them. With SQL 2005 choosing between stored procedures and dynamic TSQL is not about performance anymore although this might be opposite of truth for different database engine vendors.

So writing stored procedures is a function of style, company policy or legitimate need for encapsulation and not LINQ related.

What is the advantage of using LINQ?

These are some advantages I see in my daily interactions with LINQ: Consistent domain model(ing); hiding the mundane code (LINQ-to-SQL); big advantage over DataSets when refining or manipulating the results; to name the few. The disadvantages I have experienced are related to fighting with deeply rooted TSQL concepts  and often intimidating syntax and lack of discoverability of features.

 

I think we are seeing an tip of an iceberg with LINQ. I think LINQ will be eventually buried under fine grained components and we will part ways with developers writing LINQ queries directly (Entity Framework?). There are a lot of unanswered questions when LINQ (-to-SQL) is concerned: security,  entities with no primary key, entities with composite primary key, many-to-many relationships, globalization and such.

I am ready for next round of LINQ related goodies!

Petar.