 |
|
|
 |
|
 |
Hi,
I agree with the others, its well written but confusing.
I think you've gone too far in trying to keep it simple.
Should I create a new repository for each object?
If you were to use Student tracking as an example. Am I creating an IRepository for each Student, Class, Result etc??
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
That question is too complicated to address in this article. You will need to read the book.
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, I have used your codes in my project. But I am having one prblem. I have 2 stored procs in my database, I want to call them with some parameters, how Will I do that with my generic repository.
Regards Paraminder
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I agree with quite a few of the others that have already written comments; the code is well written. Unfortunately, it misses the point of the repository pattern. By using the classes created by LINQ to SQL, you have tied yourself to an implementation (and incidentally your database structure). You need to create model objects distinct from your LINQ to SQL classes and do your field mapping where needed. Also, the MarkForDeletion and SaveAll methods limit your underlying data access to something that keeps track of your changes.
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Liam,
Excellent article! I like your interpretation of Repository pattern very much, so much I used it. However, I needed to use Link to Entities because I'm using inheritance in my model, also I thought I would change two things to make your solution more flexible and performant. It's all simple enough so here it is:
The IRepository interface is almost identical:
using System.Linq; using System.Linq.Expressions;
namespace System.Linq.Repository { public interface IRepository<T> where T : class { /// <summary> /// Return all instances of type T. /// </summary> /// <returns></returns> IQueryable<T> All();
/// <summary> /// Return all instances of type T that match the expression exp. /// </summary> /// <param name="exp"></param> /// <returns></returns> IQueryable<T> FindAll(System.Linq.Expressions.Expression<Func<T, bool>> exp);
/// <summary>Returns the single entity matching the expression. Throws an exception if there is not exactly one such entity.</summary> /// <param name="exp"></param><returns></returns> T Single(System.Linq.Expressions.Expression<Func<T, bool>> exp);
/// <summary>Returns the first element satisfying the condition.</summary> /// <param name="exp"></param><returns></returns> T First(System.Linq.Expressions.Expression<Func<T, bool>> exp);
/// <summary> /// Mark an entity to be deleted when the context is saved. /// </summary> /// <param name="entity"></param> void MarkForDeletion(T entity);
/// <summary> /// Create a new instance of type T. /// </summary> /// <returns></returns> T CreateInstance();
/// <summary>Persist the data context.</summary> void SaveAll(); } }
And the implementation of Repository for Entities here:
using System.Linq;
namespace System.Linq.Repository { public class Repository<T> : IRepository<T> where T : class { protected System.Data.Objects.ObjectContext _dataContext;
public Repository(System.Data.Objects.ObjectContext context) { _dataContext = context; }
#region IRepository<T> Members
public IQueryable<T> All() { return _dataContext.CreateQuery<T>(typeof(T).Name); }
public IQueryable<T> FindAll(System.Linq.Expressions.Expression<Func<T, bool>> exp) { return All().Where<T>(exp); }
public T Single(System.Linq.Expressions.Expression<Func<T, bool>> exp) { return All().Single<T>(exp); }
public T First(System.Linq.Expressions.Expression<Func<T, bool>> exp) { return All().First<T>(exp); }
public void MarkForDeletion(T entity) { _dataContext.DeleteObject(entity); }
public T CreateInstance() { T entity = Activator.CreateInstance<T>(); _dataContext.AddObject(typeof(T).Name, entity); return entity; }
public void SaveAll() { _dataContext.SaveChanges(); }
#endregion } }
Please, let me know wat you think.
Thank you,
Irv
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Thanks for very good article. I request to you, in future you will write similar article for Entity Framework. I think that will very helpful for like me who are interested to use Entity Framework as OR Mapping tool.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I think it is useful. Care to elaborate on your comment?
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Firstly, thank you for not blasting me for sounding rude. Your code seems to be well thought out and well written. I have not actually stepped through it. My problem is not with your code, but with Linq to SQL, a technology I greatly enjoy but whose shortcomings give me great angst. L2S has great potential. Unfortunately, in its current implementation, as it relates to web applications, L2S is little more than a glorified pipe to a database. Dont get me wrong - There are a lot of things I like about L2S - namely entity class generation. But as far as functioning as a repository, L2S does not (for n tiered apps). The code you've written is good but in IMHO is written against a model that is not yet complete.
Here is a question I posed to Microsoft. You can read it here[^]
My basic question was: My objective is to allow the user to create an entire order without writing anything to the database. Once the user clicks save I want to write the whole thing at once. How do I accomplish that?
The relevant portion of the answer is:"...if you use entity objects to store data collected from users before submitting to the database you need to track entity state (new/modified/deleted etc) yourself across postbacks/page lifecycles and then use the L2S datacontext to read/write from the database."
So all the state tracking built into L2S is not only useless but cumbersome. L2S is not a repository. It does not afford me any mechanism for tracking entity state across layers of my application. It provides minimal support for (de)serialization, and I have to manage storage of objects in viewstate or session myself. That should be L2S's job! The code you wrote, while filling a certain need, does not appear to address this deficiency. Thus it becomes more icing on an inedible cake.
I'd love to be wrong about this because I'm knee deep in a very large app where these problems are killing my schedule!
Thanks for listening 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Good news! I think you are wrong 
I agree that Linq-to-sql has some terrible flaws. And it seems now that they will never be fixed, however, your problem is with the web and the stateless nature of the HTTP protocol. Nearly everything in a web app happens in the lifetime of a HTTP request so there is no good way to persist state across requests. The problem you described exists in linq-to-sql, nhibernate, entity framework, ruby on rails and every other web development environment.
NHibernate has a solution called session-per-conversation which effectively uses the asp.net session to store the object context between requests. The other options are to use ajax to rewrite your application so that your entire order is created in a single HTTP request. Finally you can have a way to flag the various parts of the order as not being complete until the final save.
Don't store objects in session / viewstate. There are great performance problems with such an approach. Either keep everything on the same page, or persist to the database.
I like your cake metaphor.
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
>>.....so there is no good way to persist state across requests.
So then how am I wrong?
>>The other options are to use ajax to rewrite your application so that your entire order is created in a single HTTP request. Finally you can have a way to flag the various parts of the order as not being complete until the final save.
Yikes!! Do you have any idea how difficult that would be!! Plus there are concurrency issues.
I really need a repository that is in fact, a repository. And, as you said in your article, it should be reusable, domain driven, independent, and strongly typed. I should not have to write to temp tables or wrestle with session or write out temp files. Indeed, L2S would be just fine for me if it did what it's documentation says it does.
Just a few hours ago I stumbled on .net RIA which you can read about here.[^] I'm not sure if is just another blind alley but it looks interesting.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You are wrong because you are blaming Linq-to-sql for the nature of web applications.
What you need is to be a desktop / smart client / silverlight application.
What does the linq-to-sql documentation say that is not true?
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I know I sound bitter but actually I'm not casting blame If I were to blame L2S, it would not be for the nature of web apps, but for a failure to work with the nature of web apps. I'm sure there are ways for L2S to work with a stateless protocol. You can probably think of one or two yourself right now. For example, wouldn't it be great to be able to call methods to serialize and write a datacontext to a row on a temp table. And another method to read and deserialize it. If something like that could be used with code like you've written in your article, the appearance to the other layers in the app would be one of a stateful repository. For the record I am not proposing the preceeding as a single solution to the problems I've discussed. It is just an example I've pulled out of thin air to make the point that some kind of stateful repository is not an impossible objective. It may not be optimal or scalable, but it's not impossible. See this[^]
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Is there any possibility to implement something like T FetchByKey(object key)? I tried using FindAll with a Func that checked the key property value, but of course this could not be translated to SQL so I failed.
Any ideas?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I'm a bit confused: when you create a repository, you inject an instance of IDataContextFactory. Why not an instance of DataContext itself? If the factory is important, could you provide an implementation?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
IDataContextFactory exists to provide a place to manage the scope of the datacontext. Im my case I wanted the scope of the datacontext to be a single http request.
There is an implementation of IDataContextFactory in the code download attached to this article.
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Hmm could you please check it again? I couldn't find any implementation. Do you just keep the context in HttpContext? Why put SaveAll in the factory interface, isn't it the context's concern?
I'm totally new to the DLinq stuff, and I'm trying to build my first DLinq Web site based on your article. Frankly, I don't have a clue about the scope, so any further info would be appreciated.
So, I think your article is good, but it could be improved in either removing the Factory stuff (since it's not absolutely required for DLinq and leaves questions for newbies like me), or explain a little about why do you need the Factory.
ulu
http://sm-art.biz[^]
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
I tried your approach because it sounded very nice. I do have some comments I'd like to share.
By defining your virtual methods like this: public IEnumerable<T> FindAll(Func<T, bool> exp) you create a enormous bottleneck. This is because the Func will not be (what I call) a delayed method, but it will be expanded immediately. I checked the log from the datacontext and it shows that the table is no longer queries using a where clause. Instead, a full table load is performed and the function is evaluated in memory.
However, the solution is very easy, although this mean you'll have to include the Linq assemblies to your testing bed:
protected T Single(System.Linq.Expressions.Expression<Func<T, bool>> exp) { return Items.Single(exp); }
The trick is to wrap you functions in a System.Linq expression. Client usage is exactly the same. The performance gain on my project was huge, If you consider that tables are no longer loaded completely into memory.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Thanks Rob, I will give that a go.
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Have a look at Ayende 'Oren Eini' Rahiens Rhino.Commons, where an IRepository is implemented. Especially for NHibernate.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I was curious how you are using the entity objects. Are you passing the "Shape" and "Vertex" Linq-to-SQL entities through the rest of your tiers? or are you creating separate business data transfer objects and mapping the data from the linq entity to them?
I ask because I have implemented a similar method and was curious how you got past this difficult problem.
Thank you,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Firstly, I only use one tier. The excepted definition of a tier (as opposed to a layer) is that one tier corresponds to one physical machine. Therefore, I use architectures that are multi-layered but single-tiered.
The "Shape" and "Vertex" objects are passed through the rest of my layers, within the lifecycle of a single http request.
Liam McLennan liam@eclipsewebsolutions.com.au www.eclipsewebsolutions.com.au
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
I have been using LINQ to SQL for some time now and I have discovered that LINQ to SQL with multiple repositories does not work. The reason is that when you create a repository object and add an item into it then it uses DataContext to insert the item into the database. Now, if you use some other repository and create and object and assign the object which was created from a different repository then your update, insert etc operation will fail. This is because the object1 was retrieved by other datacontext then the object2 which is being persisted by some other datacontext.
This is a big issue with LINQ to SQL. If you like to read more then check out the following post:
http://azamsharp.com/Posts/4_Dealing_With_LINQ_to_SQL_DataContext_Issues.aspx
Mohammad Azam azamsharp@gmail.com www.gridviewguy.com Houston, TEXAS
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |