I have started using Linq to SQL in a (bit DDD like) system which looks (overly simplified) like this:
public class SomeEntity // Imagine this is a fully mapped linq2sql class.
{
public Guid SomeEntityId { get; set; }
public AnotherEntity Relation { get; set; }
}
public class AnotherEntity // Imagine this is a fully mapped linq2sql class.
{
public Guid AnotherEntityId { get; set; }
}
public interface IRepository<TId, TEntity>
{
Entity Get(TId id);
}
public class SomeEntityRepository : IRepository<Guid, SomeEntity>
{
public SomeEntity Get(Guid id)
{
SomeEntity someEntity = null;
using (DataContext context = new DataContext())
{
someEntity = (
from e in context.SomeEntity
where e.SomeEntityId == id
select e).SingleOrDefault<SomeEntity>();
}
return someEntity;
}
}
Now, I got a problem. When I try to use SomeEntityRepository like this
public static class Program
{
public static void Main(string[] args)
{
IRepository<Guid, SomeEntity> someEntityRepository = new SomeEntityRepository();
SomeEntity someEntity = someEntityRepository.Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));
Console.WriteLine(someEntity.SomeEntityId);
Console.WriteLine(someEntity.Relation.AnotherEntityId);
}
}
everything works nicely until the program gets to the last WriteLine, because it throws an ObjectDisposedException, because the DataContext does not exist any more.
I do see the actual problem, but how do I solve this? I guess there are several solutions, but none of those I have thought of to date would be good in my situation.
Get away from the repository pattern and using a new DataContext for each atomic part of work.
I really would not want to do this. A reason is that I do not want to be the applications to be aware of the repository. Another one is that I do not think making linq2sql stuff COM visible would be good.
Also, I think that doing context.SubmitChanges() would probably commit much more than I intended to.
Specifying DataLoadOptions to fetch related elements.
As I want my Business Logic Layer to just reply with some entities in some cases, I do not know which sub-properties they need to use.
Disabling lazy loading/delayed loading for all properties.
Not an option, because there are quite a few tables and they are heavily linked. This could cause a lot of unnecessary traffic and database load.
Some post on the internet said that using .Single() should help.
Apparently it does not ...
Is there any way to solve this misery?
BTW: We decided to use Linq t0 SQL because it is a relatively lightweight ORM solution and included with the .NET framework and Visual Studio. If the .NET Entity Framework would fit better in this pattern, it may be an option to switch to it. (We are not that far in the implementation, yet.)
Rick Strahl has a nice article about DataContext lifecycle management here: http://www.west-wind.com/weblog/posts/246222.aspx.
Basically, the atomic action approach is nice in theory but you're going to need to keep your DataContext around to be able to track changes (and fetch children) in your data objects.
See also: Multiple/single instance of Linq to SQL DataContext and LINQ to SQL - where does your DataContext live?.
You have to either:
1) Leave the context open because you haven't fully decided what data will be used yet (aka, Lazy Loading).
or 2) Pull more data on the initial load if you know you will need that other property.
Explaination of the latter: here
I'm not sure you have to abandon Repository if you go with atomic units of work. I use both, though I admit to throwing out the optimistic concurrency checks since they don't work out in layers anyway (without using a timestamp or some other required convention). What I end up with is a repository that uses a DataContext and throws it away when it's done.
This is part of an unrelated Silverlight example, but the first three parts show how I'm using a Repository pattern with a throwaway LINQ to SQL context, FWIW: http://www.dimebrain.com/2008/09/linq-wcf-silver.html
Specifying DataLoadOptions to fetch related elements. As I want my Business Logic Layer to just reply with some entities in some cases, I do not know which sub-properties they need to use.
If the caller is granted the coupling necessary to use the .Relation property, then the caller might as well specify the DataLoadOptions.
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Entity>(e => e.Relation);
SomeEntity someEntity = someEntityRepository
.Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"),
loadOptions);
//
using (DataContext context = new DataContext())
{
context.LoadOptions = loadOptions;
This is what I do, and so far it's worked really well.
1) Make the DataContext a member variable in your repository. Yes, this means you're repository should now implement IDisposable and not be left open... maybe something you want to avoid having to do, but I haven't found it to be inconvenient.
2) Add some methods to your repository like this:
public SomeEntityRepository WithSomethingElseTheCallerMightNeed()
{
dlo.LoadWith<SomeEntity>(se => se.RelatedEntities);
return this; //so you can do method chaining
}
Then, your caller looks like this:
SomeEntity someEntity = someEntityRepository.WithSomethingElseTheCallerMightNeed().Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));
You just need to make sure that when your repository hits the db, it uses the data load options specified in those helper methods... in my case "dlo" is kept as a member variable, and then set right before hitting the db.
Related
I'm trying understand the basics of Entity Framework and I have a question about the Set<> method on DbContext. I am using a database first model for the following question.
Let's say I have an ActivityLog database which amongst other things I can use to pull out a message (NLog message, for example). I could write some code to pull out all messages like this:
using (var entities = new ActivityLogEntities())
foreach (var log in entities.AcitivityLogs)
Console.WriteLine(log.Message);
However I could also achieve the same thing doing this:
using (var entities = new ActivityLogEntities())
foreach (var message in entities.Set<ActivityLog>().Select(entity => entity.Message))
Console.WriteLine(message);
My question is what is the difference between these two statements? When is it more appropriate to use one over the other? Or is this just a matter of personal preference?
There's no significant difference. In the first case, you have something like:
class MyContext : DbContext
{
public DbSet<AcitivityLog> AcitivityLogs { get; set; }
}
When context is being created, it looks for public DbSet<T> read/write-properties, and does this (pseudo-code):
dbSetProperty = Set<EntityType>();
But, there are cases, when you:
don't want to make public properties for all of you entity types;
don't know all of the entity types at context's design time.
In these cases Set<T> is the only way to get proper entity set.
The only reason i have ever used Set<T> is when you are acting on a type you dont know, eg a generic insert.
Heres an example from my generic repository:
public void AddOnSave(T entity)
{
ctx.Set<T>.Add(entity);
}
Using it for regular stuff just makes the code less readable IMHO
If your look at the generated DbContext class you'll see that AcitivityLogs is just a DbSet<ActivityLog>.
So they are the same same thing. It's just the typed definition of your DbSet.
In the data architecture I have to contend with, there are no deletes. Instead, all records have a nullable datetime2 that signals the record has been "disabled". This means that in the cases of direct selections on the entities, I'll always have to add in a check to see if the entity was disabled or not.
So far what I've come up with is just a simple extension method called .Enabled() that gets only the enabled rows. It seems effective so far, but it's also annoying that I have to type that in every case.
Surely someone else has skinned this cat before. Is there a better way to do this with Entity Framework I'm just not privy to?
I suppose you could do something like this
public class MyContext : DbContext
{
public IDbSet<Thing> Things { get; set; }
public IQueryable<Thing> EnabledThings
{
get
{
return Things.Where(t => t.Enabled);
}
}
}
or the same as an extension method (but on the context not the DbSet/queriable).
Personally in practice I actually do exactly as you have in your example and use Things.Enabled().Whatever
I don't know of anything native to Entity Framework. But normally when I run into this, I create an "repository" layer that I run most database transactions through. Then I create methods like GetAll() which returns all items with appropriate where statement in place to hide "deleted" items.
I am building a small data intensive app with Windows Forms. In the main project I have a folder that holds my DBML as well as data classes to provide CRUD operations against the database. There are about 10 said data classes currently.
The code behind in the form instantiates business objects and makes calls against them to do all the work. These business objects are making calls against the static data access classes.
An example of a data class would be something like this
static class CustomerData
{
public static IEnumerable<Customer> GetCustomersForRun(int runID)
{
var db = new FooDataContext("connectionString");
return db.Customers.Where(ri => ri.RunID == runID);
}
}
Now obviously there are a few problems with my initial design that I need to address.
1) It's not nice to have each static method need to create its own DataContext. This doesn't seem very DRY at all.
2) Because I'm relying on some lazy loading I'm not able to wrap my DataContext in a using statement.
A couple of different ideas I have to fix this problem are
1) Get rid of the static methods and instead create an abstract base data access class that can instantiate my DataContext.
2) Have each business object create it's own DataContext and pass that into the static methods of the data access classes.
An example of the method signature would then be
public static IEnumerable<Customer> GetCustomerForRun(DataContext db, int runID)
My specific questions are
1) Am I over complicating this?
2) Do you typically dispose of your DataContext objects?
3) Which of my solutions makes most sense? If none of them what do you recommend?
1) Am I over complicating this?
It really depends if your application is very small shoehorning a pattern into the mix might make things more complicated where simply using the DataContext might make things easier to understand instead of putting a layer of abstraction on top of linq to sql.
2) Do you typically dispose of your DataContext objects?
It will depend on your implamentation, if you plan on passing an IQueryable<T> around to do filtering wrapping a using(){} block will cause your grief. Since linq to sql only triggers a sql query when you do something that calls GetEnumerator() your context might be disposed and your call will fail.
Conceder this example:
IQueryable<Table> GetStuff()
{
using(var db = new DataContext())
{
return db.Tables.Where(i=>i.Id == 1);
}
}
if in another method you try to do this GetStuff().Where(i=> i.Name == "Jon").ToList() will cause the query to fail as the context has already been disposed.
Now if you don't do that you can gain the power of IQueryable
IQueryable<Table> GetStuff()
{
return db.Tables.Where(i=>i.Id == 1);
}
GetStuff().Where(i=> i.Name == "Jon").ToList() will work and allow you to filter out your query and defer execution of the sql statement until the very last minute. More information can be found here.
3) Which of my solutions makes most sense? If none of them what do you recommend?
I usually try to stay away from static classes/methods since it makes doing unit tests very difficult. Probably some good information would be to look at the Repository pattern and this answer which gives some quick information.
I am working on converting a web application over to a WPF desktop application. I want to use the existing data access layer so I don't have to rewrite all the SQL queries.
But, as it stands, everything is populated almost purely from DataTables returned from SQL queries. To make things a bit easier to manage, in some instances, it would really be nice to convert these things into objects.
For example, I have a query that pulls out report information. I may get 500 results with columns like ReportID, ReportTitle, ReportDate.
I would like to make a report class that has these public attributes and somehow convert the SQL query results into a collection of these report objects.
What is the best way to go about doing this?
Super bonus points if there is an easy way of going backwards (updating the database if the objects are changed).
You should learn about Object-Relational Mapping (ORM). A good ORM can save you tonnes of work in the future, and gets those nasty queries out of your code.
I'd recommend NHibernate or Entity Framework 4.0
While I would also like to suggest ORM (NHibernate is the way to go:)) a possible solution is:
public IEnumerable<Report> ToReportList(DataTable dt)
{
return dt.AsEnumerable().Select(dr => new Report
{
member1 = dr["column1"].ToString(),
...
});
}
Report is your class here by the way.Such as,
internal class Report
{
public string member1{ get; set;}
...
}
You may also want to check this,
http://msdn.microsoft.com/en-us/library/Bb399375(v=VS.100).aspx
I think if you search stackoverflow, you will find nicer examples as I remember learning this from here.
By the way, if you use NHibernate, you won't have to rewrite your queries at all. All you have to do is map your tables to a class and booya you are good to go. It will handle all your DML stuff (well mostly) and you can easily tell the ORM to do LazyLoad, Batch processing etc which is pretty cool.
Super bonus points if there is an easy
way of going backwards (updating the
database if the objects are changed).
For that , go for ORM i.e. NHibernate (I know I am biased :)). For LINQ to SQL examples check the 2 links below:
http://msdn.microsoft.com/en-us/library/bb386931.aspx
http://csainty.blogspot.com/2008/01/linq-to-sql-insertupdatedelete.html
+1 ORM. Entity Framework is good, LINQ to SQL is good too, but you'd need a good database design and is better for pretty basic SQL CRUD actions. For custom entities from multiple datasources, I'd go EF.
As far as backwards updating - LINQ to SQL has an easy-peasy implementation, sorta like this - say you've got a db called MyDatabase with Dog entities in it:
using(MyDatabaseDataContext db = new MyDatabaseDataContext())
{
//LINQ will automatically pluralize your items (entity named Dog becomes Dogs)
Dog d = db.Dogs.Where(x=>x.DogName.Equals(dogName));
d.Owner = "Steve";
db.SubmitChanges();
//adding new items is easy too
Dog newdog = new Dog();
newDog.DogName = "Scruff";
newDog.Owner = "Jim";
db.Dogs.Add(newDog);
db.SubmitChanges();
}
Check out this method. First you can create a class that inherits DataContext. And then you can use methods of DataContext like to ExecuteQuery<> to convert your results in to objects. With this method you can directly use your queries you wrote earlier. Also, I feel that this way is a lot better than maintaining a .dbml file, because of the issues associated to synchronization with the actual database schema.
Consider the following example. First you need to define a class for interacting with your database
public class DBManagerDataContext : DataContext
{
private static string connectionString = ""; // Your connection string
public static DBManagerDataContext CreateInstance()
{
return new DBManagerDataContext(connectionString);
}
protected DBManagerDataContext(string connectionString)
: base(connectionString, new AttributeMappingSource())
{
}
}
Then you can use this context to execute queries and convert them in to objects as shown below:
public class Report
{
public int ReportID;
public string ReportTitle;
public DateTime ReportDate;
private static string query = "select ReportID, ReportTitle, ReportDate from dbo.Reports"; // Your query
public static List<Report> GetReportList()
{
DBManagerDataContext context = DBManagerDataContext.CreateInstance();
return context.ExecuteQuery<Report>(query).ToList();
}
}
You can use the method "GetReportList()" given above like this for example:
List<Report> reports = Report.GetReportList();
In the case of updates, the method suggested by "jdandison" is a nice option, apart from using the data context as above. In the case of updates it would be "ExecuteCommand" though. Please explore the DataContext class for more information.
Edit: Please note that the query column names should match the definition in the object
Can anyone show me simple CRUD statements for aggregate root using traditional ado.net?
Thanks in advance!
(This is written on the assumption that a GUID or some non-database generated primary key is used)
Also alot of boiler code such as connection management etc... should be moved to a base class for Repository.
If Order is the aggregate root, one possibly should make OrderLineRepo private to the assembly
public class OrderRepository : Repository
{
public void Save(Order order)
{
if(order.IsDirty)
{
//sets up connection if required, command and sql
ICommand command = BuildCommandForSave(order);
command.Execute();
OrderLineRepository orderLineRepo = GetOrderLineRepo();
foreach(OrderLine line in order.OrderLines)
{
orderLineRepo.Save(line);
}
}
}
}
However I'd stress that this is really a simple naive implementation, and that I'd personally utilize an ORM like nHibernate for my persistence if doing DDD as the requirements for a good well tested persistence layer are non-trivial
Also this assumes that the IsDirty function takes children into account - we would also require a means to see if the order is new/edited, not just dirty