LINQ to SQL & WCF

80
LINQ to SQL & WCF Using LINQ to SQL in n- Tiered architectures

description

LINQ to SQL & WCF. Using LINQ to SQL in n-Tiered architectures. Eric Phan. Solution Architect @ SSW Used LINQ to SQL since the early CTPs and Betas Used LINQ to SQL in a few large scale client applications Windows App Web Apps - PowerPoint PPT Presentation

Transcript of LINQ to SQL & WCF

Page 1: LINQ to SQL & WCF

LINQ to SQL & WCFUsing LINQ to SQL in n-Tiered architectures

Page 2: LINQ to SQL & WCF

Solution Architect @ SSW Used LINQ to SQL since the early CTPs and Betas Used LINQ to SQL in a few large scale client applications

Windows App Web Apps

In charge of Developer training and Architecture/Code reviews at SSW

http://ericphan.info

Eric Phan

Page 3: LINQ to SQL & WCF

Defining the tiers 3 tiered architecture with LINQ to SQL Working with WCF Some gotchas Some Tips

Agenda

Page 4: LINQ to SQL & WCF

What’s the worst application you have worked on? I was working on a Client project earlier…

But before I start…

Page 5: LINQ to SQL & WCF

They had a great architecture…

Database

ASP Website

Page 6: LINQ to SQL & WCF

60 tables with no relationships and keys It was crashing a lot 1000 ASP pages that managed their whole business

It had…

Page 7: LINQ to SQL & WCF

JobList.asp JobListA.asp JobListB.asp JobListForGregInAccounting.asp

There was a lot of ad hoc customizations

Page 8: LINQ to SQL & WCF

SQL Database to be cleaned up ASP to be rewritten with new functionality in ASP.NET ASP pages to be simplified Clearly defined workflow for their business processes Potentially later down the track they will have mobile

PDA or ruggedized laptops connecting to the system to access a subset of the functionality

They wanted…

Page 9: LINQ to SQL & WCF

Clean up the database Setup a good architecture with:

LINQ to SQL for data access Windows Workflow WCF for the business logic ASP.NET 3.5 Web Application Windows App [future release]

This is what we proposed

Page 10: LINQ to SQL & WCF

UIBusinessData

Northwind

Data Access

Data Access

Common Objects

LINQ to SQL DBML

WCF Service

s

WebUI

WinUI

Page 11: LINQ to SQL & WCF

Isn’t LINQ to SQL a 2 tiered technology?

How did we do it?

Page 12: LINQ to SQL & WCF

Where does LINQ to SQL fit in? The LINQ to SQL DBML consists of two main parts

DataContext – Data Access• e.g. NorthwindDataContext

Entities – objects representing data in your database• e.g. Customer, Order, Employee

It’s like your Data Adapters and Data Sets. The DataContext talks to the database and the Entities

just hold the data

Page 13: LINQ to SQL & WCF

By default it is 2 tiered I can call my data access from my Web using (var db = new NorthwindDataContext())

{ return db.Customers.ToList();}

2 Tiered?

Page 14: LINQ to SQL & WCF

Data

Northwind

Data Access/ClassesNorthwind.Common.Objects

DataContextEntities

Page 15: LINQ to SQL & WCF

UIData

Northwind

Data Access/ClassesNorthwind.Common.Objects

DataContextEntities

WebUI

WinUI

Page 16: LINQ to SQL & WCF

UIData

Northwind

Data Access/ClassesNorthwind.Common.Objects

DataContextEntities

WebUI

WinUI

Page 17: LINQ to SQL & WCF

UIData

Northwind

Data Access/ClassesNorthwind.Common.Objects

DataContextEntities

WebUI

WinUI

Business

Services

Page 18: LINQ to SQL & WCF

The entities should be shared across all the projects UI needs to know how to present the customer Business logic needs to know what to do with a

customer Data access needs to know how to get and update

a customer What about the DataContext?

It’s currently bundled with the entities Can we split it?

Where does LINQ to SQL fit in?

Page 19: LINQ to SQL & WCF

Has anyone tried?

Can we split it?

Page 20: LINQ to SQL & WCF

Create our own generic DataContext class in a new DataAccess project.

Create some methods in NorthwindData.cs to get and save data.

Make the generated DataContext class internal

So how do we separate our Data Access layer?

Page 21: LINQ to SQL & WCF

I would automatically separate the DataContext and Entities into two different projects or at least two different class files

You can achieve this through various techniques and code generators (e.g. generating XML using SQLMetal then using XSLT to create your Entity classes), but it’s not nice. This stuff really should be supported out of the box.

There are several projects out there that attempt to create this separation.

I find it easier just to create this generic DataContext

If I was the God of LINQ to SQL…

Page 22: LINQ to SQL & WCF

So how does our architecture look now?

Page 23: LINQ to SQL & WCF

UINorthwind.ServicesData

Northwind

Northwind.DataAccess

NorthwindData

Northwind.Common.Objects

Northwind.dbmlInternal DataContext

Entities

Services

WebUI

WinUI

Page 24: LINQ to SQL & WCF

Has anyone tried to use LINQ over WCF? Any problems? Any success stories?

Let’s talk business over WCF

Page 25: LINQ to SQL & WCF

Service Contracts Defines a set of contracts between the client and the

server so they know how to communicate [ServiceContract] – marks a class as visible to WCF clients [OperationContract] - marks a method as visible to WCF

clients [DataContract] – marks a class as transportable over WCF [DataMember] – marks a property on the class to serialize

WCF

Page 26: LINQ to SQL & WCF

Can easily configure how the service behaves E.g. listen over HTTP, TCP IP, UDP Enable reliable messages Enable encryption Enable security

Hosting via IIS Windows Service Console

WCF

Page 27: LINQ to SQL & WCF

Get a list of customers Delete some customers Update customer details View the orders a customer has made

Let’s talk business over WCF

Page 28: LINQ to SQL & WCF

Our WCF service is running

Page 29: LINQ to SQL & WCF

WCF Service Configurator

Page 30: LINQ to SQL & WCF

Data

Northwind

Page 31: LINQ to SQL & WCF

Data

Northwind

Northwind.Common.Objects

Northwind.dbmlwith Internal DataContext

Page 32: LINQ to SQL & WCF

Data

Northwind

Northwind.DataAccess

NorthwindData

Northwind.Common.Objects

Northwind.dbmlwith Internal DataContext

Page 33: LINQ to SQL & WCF

Northwind.ServicesData

Northwind

Northwind.DataAccess

NorthwindData

Northwind.Common.Objects

Northwind.dbmlwith Internal DataContext

Northwind.Service

s

Page 34: LINQ to SQL & WCF

Northwind.WebUI

Northwind.ServicesData

Northwind

Northwind.DataAccess

NorthwindData

Northwind.Common.Objects

Northwind.dbmlwith Internal DataContext

Northwind.Service

s

WebUI

WinUI

Page 35: LINQ to SQL & WCF

Make our client talk to the WCF services

Connecting the Client

Page 36: LINQ to SQL & WCF

Error #1 – Connection String

Page 37: LINQ to SQL & WCF

Where should I put it? A) Northwind.Common.Objects B) Northwind.DataAccess C) Northwind.Services D) Northwind.WebUI

Error #1 – Connection String

Page 38: LINQ to SQL & WCF

A:\ A) Northwind.Common.Objects B) Northwind.DataAccess C) Northwind.Services D) Northwind.WebUI

Let’s fix this and continue

Error #1 – Connection String

Page 39: LINQ to SQL & WCF

Error #2 – Underlying connection was closed

Page 40: LINQ to SQL & WCF

Has anyone come across this one? There’s not much details if you actually debug through

it

Error #2 – Underlying connection was closed

Page 41: LINQ to SQL & WCF

This is a WCF serialization issue Whenever you come across this error, 90% of the time

it’s because one of the objects/classes you are passing back from WCF can’t be serialized.

We need to make our LINQ classes serializable.

Error #2 – Underlying connection was closed

Page 42: LINQ to SQL & WCF

Serializable LINQ to SQL classes

Page 43: LINQ to SQL & WCF

[Table(Name="dbo.Customers")][DataContract()]public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged{

[Column(Storage="_CustomerID", DbType="NChar(5) NOT NULL", CanBeNull=false, IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)] [DataMember(Order=1)]

public string CustomerID

Serializable LINQ to SQL Classes

Page 44: LINQ to SQL & WCF

Error #3 – Maximum Message Size

Page 45: LINQ to SQL & WCF

Who wants to give up? Who’s hit this before? What did you do?

Error #3 – Message Size

Page 46: LINQ to SQL & WCF

Who wants to: A) Change the default size to the maximum

possible size B) Return less than 64K of data

Error #3 – Message Size

Page 47: LINQ to SQL & WCF

Who wants to: A) Change the default size to the maximum

possible size B) Return less than 64K of data

Error #3 – Message Size

Page 48: LINQ to SQL & WCF

This one is actually a very good issue to hit early Essentially what is happening here is that we’re doing

a SELECT * FROM Customers Does anyone have a problem with this? What if there were 100000 records?

Error #3 – Message Size

Page 49: LINQ to SQL & WCF

WCF is smart and doesn’t attempt to send any messages that are over a certain limit (by default it’s 64K)

Saves your end users from waiting a long time to load a page

Error #3 – Message Size

Page 50: LINQ to SQL & WCF

The right thing to do here is to change our query to use paging

Error #3 – Message Size

Page 51: LINQ to SQL & WCF

Message Size public List<Customer> GetCustomers(int pageIndex, int pageSize, out int totalCustomers) { using (var db = new NorthwindData()) { var customers = db.GetTable<Customer>(); totalCustomers = customers.Count();

var results = customers .Skip(pageIndex*pageSize) .Take(pageSize);

return results.ToList(); } }

Page 52: LINQ to SQL & WCF

Message Size

Page 53: LINQ to SQL & WCF

Creating a WCF service and hooking it up and these common issues Connection strings Serialization Message Size

What we saw

Page 54: LINQ to SQL & WCF

After this we will cover Deletes Updates Eager Loading

Lets take a break

Page 55: LINQ to SQL & WCF

Delete Customer Details Update

Lets add some more functionality

Page 56: LINQ to SQL & WCF

Delete

Page 57: LINQ to SQL & WCF

We solved it by deleting the references also You can also set Cascade deletes on in the database

Delete

Page 58: LINQ to SQL & WCF

Customer Details

Page 59: LINQ to SQL & WCF

Customer Details

Page 60: LINQ to SQL & WCF

Databinding through the UI against an object data source and our WCF service client

0 code in the UI

Customer Details

Page 61: LINQ to SQL & WCF

Should be easy…

Updates

Page 62: LINQ to SQL & WCF

Update Error #1

Page 63: LINQ to SQL & WCF

Fixed by adding Timestamp columns

Update Error #1

Page 64: LINQ to SQL & WCF

Update Error #2

Page 65: LINQ to SQL & WCF

Caused by the attach method just connecting the disconnected entity but not actually checking to see if there were any changes

As Modified parameter Fixed by using Context.Refresh()

Update Error #2

Page 66: LINQ to SQL & WCF

Cannot add an entity with a key that is already in use. Value of member 'TimeStamp' of an object of type

'Customer' changed. A member that is computed or generated by the

database cannot be changed.

Some other errors

Page 67: LINQ to SQL & WCF

A couple of strategies Timestamp column Reflection to replay changes Keep a copy of the original Use the Attach & Refresh method

(recommended)

LINQ to SQL - Updates

Page 68: LINQ to SQL & WCF

public void UpdateCustomer(Customer customer) { using (var db = new NorthwindData()) { db.GetTable<Customer>().Attach(customer, true); db.GetTable<Customer>().Context.Refresh(RefreshMode.KeepCurrentValues,

customer); db.Save(); } }

Updates - Attach and Refresh

Page 69: LINQ to SQL & WCF

It works!!!

Page 70: LINQ to SQL & WCF

Show the orders for a customer when you show the customer details

Lets do one more thing and load some orders

Page 71: LINQ to SQL & WCF

Use this when you need to bring along child objects with you

Saves you from doing another round trip Only works in one direction

Eager Loading with DataLoadOptions and LoadsWith

Page 72: LINQ to SQL & WCF

E.g. When viewing an order you can’t get it to eagerly load a Customer. order.Customer will be null order.CustomerID will have the CustomerID

Eager Loading with DataLoadOptions and LoadsWith

Page 73: LINQ to SQL & WCF

Why does it only work in one direction?• Remember the unidirectional serialization?• Uni means one

One way serialization

Page 74: LINQ to SQL & WCF

Requery for it as you will have access to the foreign keys

Create an aggregate class that will return what you need class OrderResult

{Customer customer;Order order;

}

What if I needed to access a parent object as well?

Page 75: LINQ to SQL & WCF

Make the generated DataContext internal Create your own generic one in DataAccess WCF

Serialization Gets – always page Updates – Attach & Refresh Eager Loading with DataLoadOptions and

LoadsWith<T>

Recap

Page 76: LINQ to SQL & WCF

We have used LINQ to SQL on several client projects Our developers love using it If you setup the architecture correctly then it is fine for

use Performance is faster than LINQ-to-Entities

http://www.thedatafarm.com/blog/2008/07/10/LookingAtEFPerformanceSomeSurprises.aspx

Is this ready?

Page 77: LINQ to SQL & WCF

We had a hard time looking at their existing system and couldn’t get a hold of the previous developer…

We eventually figured things out It was a 6 month project We had up to 8 developers working on the project It is currently in testing by the client

With our client from before

Page 78: LINQ to SQL & WCF

Rules to Better LINQ www.ssw.com.au/ssw/Standards/Rules/RulesToBetterLinq.a

spx Julie Lerman – Microsoft MVP, LINQ, EF guru

http://www.thedatafarm.com/blog/ Hooked on LINQ

http://www.hookedonlinq.com WCF Samples

http://msdn.microsoft.com/en-us/library/ms751514.aspx

Resources

Page 80: LINQ to SQL & WCF

Thank You!

Gateway Court Suite 10 81 - 91 Military Road Neutral Bay, Sydney NSW 2089 AUSTRALIA

ABN: 21 069 371 900

Phone: + 61 2 9953 3000 Fax: + 61 2 9953 3105

[email protected]