views:

1536

answers:

3

I get the concept of creating a business object or entity to represent something like a Person. I can then serialize the Person using a DTO and send it down to the client. If the client changes the object, it can have an IsDirty flag on there so when it gets sent back to the server I know to update it.

But what if I have an Order object? This has the main header informaton, customer, supplier, required date, etc. Then it has OrderItems which is a List< OrderItem>, being the items to be ordered. I want to be able to use this business object on my UI. So I have some textboxes hooked up to the location, supplier, required date, etc and a grid hooked up to OrderItems. Since OrderItems is a List I can easily add and delete records to it. But how do I track this, especially the deleted items. I don't want the deleted items to be visible in my grid and I shouldn't be able to iterate over them if I used foreach, because they have been deleted. But I still need to track the fact there was a deletion. How do I track the changes. I think I need to use a unit of work? But then the code seems to become quite complex. So then I wonder why not simply use DataTables and get the change tracking for free? But then I read how business objects are the way to go.

I’ve found various examples on simple Person examples, bnut not header-detail examples like Orders.

BTW using C# 3.5 for this.

A: 

the data objects don't track changes. the change tracking occurs on the DataContext and objects that you've retrieved through the DataContext. So in order to track changes you need to do the following:

public class FooDataContext : DataContext
{
   public Table<Order> Orders;   
}

public class Order
{
        [DbColumn(Identity = true)]
        [Column(DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
        public int Id { get; set; }

        [DbColumn(Default = "(getutcdate())")]
        [Column(DbType = "DateTime", CanBeNull = false, IsDbGenerated = true)]
        public DateTime DateCreated { get; set; }

        [Column(DbType = "varchar(50)", CanBeNull = false, IsDbGenerated = false)]
        public string Name { get; set; }
}

Now in your codebehind you can do something like:

public void UpdateOrder(int id, string name)
{
   FooDataContext db = new FooDataContext();
   Order order = db.Orders.Where(o=>o.Id == id).FirstOrDefault();

   if (order == null) return;

   order.Name = name;

   db.SubmitChanges();
}

I wouldn't recommend directly using the data context in the code behind, but this is a good way to get started with Linq To SQL. I would recommend putting all your database interactions in an external project and call from the GUI to the classes that encapsulate this behavior.

I would recommend creating a Linq To Sql (dbml) file if you're new to Linq To Sql.

Right click on your project in solution explorer, and select Add New Item. Select Linq To SQL file, and it will then let you connect to your database and select the tables.

You can then look at the generated code, and get some great ideas on how Linq To Sql works and what you can do with it.

Use that as a guideline on working with Linq to SQL and that will take you far...

Code Monkey
way out of topic !!
jalchr
+4  A: 

Firstly, you can use an existing framework that addresses these issues, like CSLA.NET. The author of this framework has tackled these very issues. Go to http://www.rockfordlhotka.net/cslanet/ for this. Even if you don't use the full framework, the concepts are still applicable.

If you wanted to roll your own, what I've done in the past was to instead of using List for my collections, I've used a custom type derived from BindingList. Inhereting from BindingList allows you to override the behaviour of add/remove item. So you can for example have another internal collection of "delteted" items. Every time the overriden Remove method is called on your collection, put the item into the "deleted" collection, and then call the base implementation of the Remove method. You can do the same for added items or changed items.

Ilya Tchivilev
A: 

You're spot on about needing a unit of work, but don't write one. Use NHibernate or some other ORM. That is what they're made for. They have Unit of Works built in.

Business objects are indeed "the way to go" for most applications. You're diving into a deep area and there will be much learning to do. Look into DDD.

I'd also strongly advise against code like that in your code-behind. Look into the MVP pattern.

I'd also (while I was bothering to learn lots of new, highly critical things) look into SOLID.

You may want to check out JP Boodhoo's nothing but .net course as it covers a lot of these things.

aaronjensen