Pure Krome

Hi folks,

I'm trying to get my head around this and i'm not having much luck, even after reading some previous 3-Tier threads in this forum *blush*. I'll try using examples, using the northwind db.

I have created a project called BLL, with a namespace called Northwind.BLL . In that project i have created dbml file called Northwind.dbml with Product and Category (just like ScottGu's linq examples). Next, to be tricky, i've set the following properties on this dbml file:

a) Context Namespace: Northwind.DAL

b) Entity Namespace: Northwind.DAL

Ok. now, what i want to do is create a class called Product, which has some static methods on it. Lets start with Load.

Code Block

eg. public static Product LoadByID(int ID)

{ ... }

what i've actually done, and i'm not sure this is the right thing, was the create the following

Code Block

public class Product : Northwind.DLL.Product

{

public static Product LoadByID(int ID)

{ ... }

}

I inherited the DLL.Product so i didn't have to define all the properties again. I feel like this is not a good thing to do Sad Secondly, i'm not sure how i can return an instance of a BLL.Product with the DLL.Product data loaded, say .. using a simple Linq query like...

Code Block

public static Product LoadByID(int ID)

{

MercuryDataContext db;


using (db = new MercuryDataContext())
{
var product = (from p in db.Products
where p.ProductID = ID

select p).SingleOrDefault();

return product != null product as Product: null; // ** THIS WILL ALWAYS RETURN NULL .. it's wrong.
}
}

Of course that last line is wrong .. it will always be null because a DLL.Product is not a BLL.Product.

So .. i've really got this wrong. Could someone explain how i can use the LINQ smarts in my logic layer without having to re-create all the properties in the logic layer, setting them, then returning the instance

an example of how this BLL.Product will be used, would be in the code behind on some ASP.NET page .. ie. my UI/Presentation layer.




Re: LINQ Project General Another Linq 3-Tier question

Joe Albahari

To do the equivalent of the following:

return product != null product as Product: null;

you'd have to write a method in the base class that copied the instance of DLL.XXX to a newly instantiated BLL.XXX, using reflection to query its properties and then dynamically invoke and copy over the members of the same name.

I'm curious, though, as to why you need separate DLL and BLL classes - especially given this is an ASP.NET application. You won't be exposing any classes directly to the client - so why not just have one set of LINQ to SQL entity classes

Regards

Joe









Re: LINQ Project General Another Linq 3-Tier question

Pure Krome

Joe Albahari wrote:
so why not just have one set of LINQ to SQL entity classes

Hi Joe Smile

That's what i sorta of want to do. If i have a number of pages that want to load a product by ID, i want to put the code for that in one place. For me, that's where by Logic Layer comes in handy. One place to load a product by ID and it can be used in multiple asp.net web forms.

So if that was the case, how could we do that I created a Business Logic Layer project to represent any 2nd tier logic stuff, which is only ever used by the presentation layer -> the asp.net web forms.

Maybe i have this stuff really wrong






Re: LINQ Project General Another Linq 3-Tier question

Joe Albahari

To put it another way, could BLL.Product.LoadByID() return a DLL.Product object

Then BLL.Product wouldn't need to subclass DLL.Product - and BLL.Product would consist purely of static methods.

Would this cause any problems with your design


Regards

Joe





Re: LINQ Project General Another Linq 3-Tier question

Pure Krome

Yep, the DLL.Product.LoadByID() could return a DLL.Product object, but as far i as know, you don't want your presentation layer to know anything about data level objects, let alone use them.

This means that the consumer on the presentation layer would be mixing both business logic and data objects -- having to manipulate TWO types of objects, confussing the usage of them both.

I'm under the impression that the consumer should only deal with one object type, and wether that business logic object uses a database or not should not be upto the presentation layer to decide.

so in summary -> this would cause a serious problem with my design IMO Sad






Re: LINQ Project General Another Linq 3-Tier question

Joe Albahari

I would agree completely if this were a 3-tier (rich client) application: it's then desirable for the client to be given only higher-level business entity objects - and not know about the database-level objects. This is exactly how we've written our recently completed 3-tier LINQ app.

But given that this is an ASP.NET app, with the (server-side) presentation and business layers running in the same app domain and fully trusting each other, I just wondered if this level of abstraction might be overkill. You've probably thought this through.


Regards

Joe







Re: LINQ Project General Another Linq 3-Tier question

WilliamStacey

Joe Albahari wrote:
I would agree completely if this were a 3-tier (rich client) application: it's then desirable for the client to be given only higher-level business entity objects - and not know about the database-level objects. This is exactly how we've written our recently completed 3-tier LINQ app.

But given that this is an ASP.NET app, with the (server-side) presentation and business layers running in the same app domain and fully trusting each other, I just wondered if this level of abstraction might be overkill. You've probably thought this through.


Regards

Joe

I am tending to think this way. Especially if you just end up creating the exact same classes as the linq entities with just different class names but same properties. If this is the case, then it would seem to be a waist of energy to gain some glass-tower-abstraction-level because the "experts" say so (we still need common sense and weight the costs). On the flip side, I think we tend to find out pretty fast when you need another level of abstraction. So I guess it will always depend on what your doing.





Re: LINQ Project General Another Linq 3-Tier question

Keith Farmer

I did some thinking on this, myself. I have, actually, thought about it a lot over the last couple years. Here's my take on it: http://blogs.msdn.com/kfarmer/archive/2007/11/06/linq-and-3-tier-dogma.aspx






Re: LINQ Project General Another Linq 3-Tier question

Pure Krome

Holy Molly Keith - an absolutely BRILLIANT post. What you're thinking about is what i've tried to start with, in my initial post.

I'll quote some points from your blog which i with to highlight as some similar thinking to myself

"ProductDataObject" and "ProductLogicalObject" in the same project, when the shapes of the two are the same. You'll spend all your time copying property values back and forth, your references won't track well, and you'll forgo any change- or identity- tracking that the data layer happens to give you.

LINQ to SQL's already encapsulated your database access code (that is why it was written); it's all contained in System.Data.Linq.dll and your mapping metadata. It also already talks in terms of your logical model, and that's fine because we already said that was what LINQ to SQL was designed to do.

Encapsulate your data context.

To me, those 3 quotes are the main points i found and agreed completely with. That said, I wish to explore them further and see your thoughts on this.

In my initial post for this thread, I was trying to encapsulate my data context. I tried to do this by inheriting my ProductDataObject as a way to encapsulate all product related stuff into the same object. Here's a great example you (Keith) did on encapsulating some commonly called code, IMO:

Code Block

// I prefer IQueryable, because I want my filtering and sorting to happen at the server, not the client.
// That is, I want to write: logicLayer.GetCustomersInWa().OrderBy(c => c.Age)
public IQueryable<Customer> GetCustomersInWA()
{

return db.Customers.Where(c => c.State == "WA").OrderBy(c => c.LastName).ThenBy(c => c.FirstName);

}

I was trying to do something similar to that above, but i was wanting to return a SINGLE Customer. As such I wasn't sure how to do this because i suppose I didn't want the user to know about the linq customer.

I'm trying to have my cake and eat it.

I want to use the Linq to Sql classes to their full potential. I also want to encapsulate the Linq queries in a more logical class - especially when it comes to reuse and readability. Lastly i was hoping to have it so that there wouldn't be two different classes being used by the consumers.

This is important to me when i have

1) webservice project

2) web site project

3) mobile web site project, possibly.

Looking forward to your thoughts Keith Smile






Re: LINQ Project General Another Linq 3-Tier question

devnet247

I have to say that your blog and post really clarified to me on how to use LinqToSql effectively!.

Correct me if I am wrong but what you actually saying is

  • Client
  • Logic Layer (Business and Linq Queries)
  • SqlServer

More Importantly is the way you pass your data around.Your suggested approach which gives Linq the full power is to return IQueryable to the Client so that the Sorting/filtering happens on the server however the execution happens on the Client,which I am not that sure about.Am I getting this wrong

I think that using Linq the way you describe is a breeze and very easy.

However one begs the question whether you want to tightly couple your object to a LinqSql Type.

I think that many of us because if you allow me lack of good examples around and guidance on how to best use it,

has left us in using Linq in a way that is not meant to be and causing all loads of issues with attaching/detaching and so on....

Which then direct to the next question

When should I use LinqToSql and when I should use EntityFramework

This guy @ Microsoft gave a very good explanation

https://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1935713&SiteID=1&pageid=0

thanks again for a very clear post about Linq.






Re: LINQ Project General Another Linq 3-Tier question

Keith Farmer

Ah, here's where I think some fun can be had.

I think this be a fruitful path to explore:

  • Web service: uses a data context directly, includes a SubmitChanges method. The standard Attach story we've been telling folks about. Whenever possible, the web service returns full entities for queries.
  • Client: holds a custom class that encapsulates a change tracking system as well as the proxy to your web service. The proxy will provide access to queries that are available from the web service. It will provide some form of identity tracking: if the service returns an entity whose key has been seen before, the query will use the existing object instead of a new one. It will also provide some form of change tracking, and a SubmitChanges which collects the current and original values of those entities which have changed, and passes them back to the web service.

You *could* use a data context purely for change tracking on the client side (just attach the entities as unchanged before you return them to the caller, and later call GetChangeSet on the context), but identity tracking wouldn't happen cleanly -- you'd be catching exceptions to detect whether you'd seen an entity before.

This is a SPROC-like approach, and unfortunately all your sorting and filtering ends up happenning on the client side. It is, however, not that difficult (at least, at first and second glances).

Unless...

... you write a provider which understands how to package up where, orderby, and the like, and submit them back to the web service (see http://blogs.msdn.com/mattwar). If you really wanted to get interesting, you *could* just have a web service which just had a SubmitChanges, and a method which took a serialized representation of an expression tree. If your web service were public, this wouldn't necessarily be a good choice, but if it were private or otherwise secured, it could be interesting. Given that it's your service, you could lock it down to specific tables, columns, or other rules.

That way, you *could* issue queries such as:

Code Block

var q = (from c in ws.Customers

where c.Name == "Frobnoz the Magnificent"

orderby c.Age descending

select c).First();

q.Age += 1;

ws.SubmitChanges();

It's certainly more work, but you can limit the scope of the effort, and it'd be a flexible approach.

Either approach amounts, effectively, to writing some form of "LINQ to Web Service". There are examples of this sort of thing float around the web.






Re: LINQ Project General Another Linq 3-Tier question

Keith Farmer

devnet247 wrote:
  • Client
  • Logic Layer (Business and Linq Queries)
  • SqlServer

That is what I'm saying.

devnet247 wrote:

More Importantly is the way you pass your data around.Your suggested approach which gives Linq the full power is to return IQueryable to the Client so that the Sorting/filtering happens on the server however the execution happens on the Client,which I am not that sure about.Am I getting this wrong

That's what I'm suggesting. Otherwise you lose a lot of the benefits of using expression trees. Remember that in this approach, your "client" is in-process with everything else. For disconnected clients, see my response to krome.

devnet247 wrote:

However one begs the question whether you want to tightly couple your object to a LinqSql Type.

That's up to you. If you're in control of both client and server (nobody else is going to write a client) then it doesn't matter. The only reason to decouple in that fashion is to create a contract such that *others* can implement it. If nobody else is going to implement it, then you can do what you want. It's a private matter in which they cannot tell the difference.

And decoupling can be as easy as creating an interface.

devnet247 wrote:

When should I use LinqToSql and when I should use EntityFramework

This guy @ Microsoft gave a very good explanation

https://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1935713&SiteID=1&pageid=0

I agree with Michael. If your models don't agree, and it's difficult to write an adapter layer over LINQ to SQL, then dump LINQ to SQL and switch to the Entity Framework, and let it handle the mapping for you. Remember: the tools serve you, not the other way around.






Re: LINQ Project General Another Linq 3-Tier question

Pure Krome

Keith Farmer wrote:
devnet247 wrote:
  • Client
  • Logic Layer (Business and Linq Queries)
  • SqlServer

That is what I'm saying.

Hi Smile

Keith, could u please expand on the LOGIC LAYER suggestion above, through the use of some code / classes / northwind db

eg. encapsulate the products table, returning a list of products for a name and a single product for an ID. I'm very interested to see some real world examples of this, if you would be so kind. Thank you so much, in advance!






Re: LINQ Project General Another Linq 3-Tier question

Pure Krome

* Pure Krome very politely bumps this thread Smile






Re: LINQ Project General Another Linq 3-Tier question

ehauser

I wrote up how to create a generic repository pattern with LINQ to SQL Not sure if this would be helpful or not:

http://www.hausertechnologies.com/wordpress/ p=36

Would not mind some feedback from those who are smarter than me either =).