473,624 Members | 2,290 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Domain Model - Collections/Transactions

I am trying to design a good domain model for a system I am working on
but I am having a hard time trying to figure out how to deal with
relations and transaction...

For example if I create an Invoice object and then add LineItem objects
to the invoice all in memory. How do I get everything to commit to the
database in the right order.

Invoice invoice = new Invoice();
invoice.OrderDa te = DateTime.Now;
invoice.Comment s = "Thank you for your order";
invoice.ToAddre ss = "Joe Blow 123 Drive Somewhere,CA.";

InvoiceItem item = new InvoiceItem();
item.Name = "Large Widget";
item.Price = 20.00;
item.Quantity = 5;

invoice.AddItem (item);

item = new InvoiceItem();
item.Name = "Small Widget";
item.Price = 15.00;
item.Quantity = 2;

invoice.AddItem (item);
invoice.Save();

One way is to implement by Save() method like this:

public void Save()
{

MapperClass.Sav eInvoice(this);

foreach(Invoice Item item in Invoice.Invoice Items)
{
MapperClass.Sav eItem(item,this .InvoiceID);
}
}

The problem is that when looking at an existing Invoice object items
like: invoice.Invoice Items it will return a collection of InvoiceItems
from the database (lazy loaded). I need users of the object model to
be able to insert, update, and delete objects in this collection and
when Save is called figure out what to do...

I can't decide how and where to track the state of objects related the
invoice object. For example when an object is removed from a
collection I still need sitting around somewhere so when I commit to
the database I know to actually remove from the DB. If was completely
removed from the collection entirely I wouldn't have any to know that
it was removed.

Where and how to I track the state of the related objects?

As properties on all my entity objects (I set the properties when items
are added and remove from collections)?

Should my invoice object maintain seperate internal arrays of objects
that need to be removed and inserted for each related object?

I have read about using a "Unit of Work" object, is this a solution to
the problem?
Thanks

Nov 16 '05 #1
3 2340
Hey Josh :)

aa7im wrote:
I am trying to design a good domain model for a system I am working on
but I am having a hard time trying to figure out how to deal with
relations and transaction...

For example if I create an Invoice object and then add LineItem objects
to the invoice all in memory. How do I get everything to commit to the
database in the right order.
That's the task of the O/R mapper you're using. Simply assign the
objects to eachother, like invoiceItem.Inv oice = invoice; or:
invoice.Invoice Items.Add(item) ;
and in the end call invoice.Save();
The problem is that when looking at an existing Invoice object items
like: invoice.Invoice Items it will return a collection of InvoiceItems
from the database (lazy loaded). I need users of the object model to
be able to insert, update, and delete objects in this collection and
when Save is called figure out what to do...
Objects need state tracking, i.e.: you need to be able to determine
that an entity's data has been altered.
I can't decide how and where to track the state of objects related the
invoice object. For example when an object is removed from a
collection I still need sitting around somewhere so when I commit to
the database I know to actually remove from the DB. If was completely
removed from the collection entirely I wouldn't have any to know that
it was removed.

Where and how to I track the state of the related objects?
This is a tough question to answer. The problem is that there is no
real solution, only a solution within a 'context'. If an InvoiceItem
changes, is the Invoice item also changed ? If the answer is yes, then
every entity change will affect the complete graph of entities in
memory. If the answer is no, you need local state tracking, i.e. for
each related entity you need a hashtable for each version of your
entity. (or other construct, as long as you can store a version of an
entity or entity collection in a construct).

The problem with state tracking in the way you want it is: "What if the
user clicks 'Cancel'?". You have these entities, you open a gui form,
the user makes a lot of changes, but then decides not to go through with
it and clicks cancel. The entities were for example databound to the
controls and are after that useless, because their state is changed.
What to do? With change tracking, you could roll back to a version prior
to the gui form being opened, but that gives problems as well.
Should my invoice object maintain seperate internal arrays of objects
that need to be removed and inserted for each related object?
Often developers keep track of changes on collections with separate
collections indeed, though just for deleted entities from collections,
i.e.: removed entities from collections. You can do two things:
- add the removed entity to a collection and delete that collection in
one go at the end
- simply log a delete action for that particular entity.
I have read about using a "Unit of Work" object, is this a solution to
the problem?


UnitOfWork, as we also support it, is a tracker for changes which are
performed. You can see it as a grouping mechanism of actions performed
on the entities in the scope of the unitofwork. The scope of the
unitofwork can be: all entities read/created with the mapper (generally
the case) or the entities added to the unitofwork. You perform the
actions on the entities and at the end commit the unitofwork. As all
actions are logged in the unitofwork, this will be your only action.

Frans.

--
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET Blog : http://weblogs.asp.net/FBouma
Microsoft MVP (C#)
Nov 16 '05 #2
Thanks Frans!

I was wondering if you would come across this post. I have been using
your product on alot large-scale applications and it has been working
great. I have not had to worry about implementing all my above issues
becuase they are all solved by your product. However the company I am
currently doing a project for will not use any code-generation tools
(not internally built) which means I am having to create a framework to
essentially accomplish the same things your product already provides
(big waste of time).

Ok... here are the issues I am running into:

Invoice invoice = new Invoice();

InvoiceItem item = new InvoiceItem();
item.IsNew = true; //This property is actually set internally in the
constructor
item.Name = "Large Widget";
item.Price = 20.00;
item.Quantity = 5;

invoice.Invoice Items.Add(item) ;

Ok... the confusing part with this is that the "InvoiceIte m" object has
a Save() method on it. If I were to execute the Save() method on the
invoiceItem object it would fail because the Invoice object has not
been saved yet (no invoiceID available). So the Save() would only be
used in cases where you want to commit changes to a "Modified"
InvoiceItem object.

The other issue is differentiating between a "new object" and an object
being "new to the collection". In the save method for the invoice
object I must save the invoice then walk through the InvoiceItem
collection looking for "new relations" and then save the object if it
is dirty then create the relation.

Will this work?

//Save method for Invoice
public void Save()
{
InvoiceMapper.S ave(invoice);

foreach(Invoice Item item in invoice.Invoice Items)
{
if(item.Invoice == null)
item.Invoice = this;
if(item.IsDirty )
item.Save();
}
}

Nov 16 '05 #3
aa7im wrote:
I was wondering if you would come across this post. I have been using
your product on alot large-scale applications and it has been working
great. I have not had to worry about implementing all my above issues
becuase they are all solved by your product. However the company I am
currently doing a project for will not use any code-generation tools
(not internally built) which means I am having to create a framework to
essentially accomplish the same things your product already provides
(big waste of time).
... some people...
Hang in there, buddy!
Ok... here are the issues I am running into:

Invoice invoice = new Invoice();

InvoiceItem item = new InvoiceItem();
item.IsNew = true; //This property is actually set internally in the
constructor
item.Name = "Large Widget";
item.Price = 20.00;
item.Quantity = 5;

invoice.Invoice Items.Add(item) ;

Ok... the confusing part with this is that the "InvoiceIte m" object has
a Save() method on it. If I were to execute the Save() method on the
invoiceItem object it would fail because the Invoice object has not
been saved yet (no invoiceID available). So the Save() would only be
used in cases where you want to commit changes to a "Modified"
InvoiceItem object.
This is a complex issue, it took me a lot of time and pilot projects to
get this right.

In the situation of a Save() method inside an entity, an entity has to
know internally what its depending entities are and what its dependent
entities are. In your example, invoice knows that invoiceItems are
depending entities.

What I do is this: when you add an entity to a collection which is part
of an entity (like you do in invoice.Invoice Items.Add(item) ; ) or when
you do: item.Invoice = invoice;, I set up synchronization information
between the two entities. This sync information is used when an entity
is saved and its PK has to be synchronized with related entities, like
when the invoice is saved, its PK has to be written in the FK fields in
all items related to that invoice item. (it doesn't matter where this
info is stored, as long as the engine saving the entity can access it).

When you save entity E, the save routine has to check if the save
routine is recursive. Sometimes you don't want to save recursively, but
say it is the default. Then you first start a transaction. Then you
check which entities are dependent from the POV of the entity to save.
In the case of an invoiceItem, that's its invoice object. This
information has to be stored somewhere, for example inside the
invoiceItem object. (it is sometimes better to store this info inside
the entity itself, so in remoting scenario's you don't lose information
and it can be used completely disconnected from the O/R mapper core).

The save routine sees there are dependent objects, so it adds these to
the transaction and simply calls the save routine of these objects
first. When an entity is saved correctly, it will fire an event, and the
handler of that event handles the synchronization action. When the call
comes back to the original save routine, all dependent objects are
saved, the FK's are synced and the invoiceItem object is ready to be saved.

After an entity is saved you can decide to save the depending objects
before returning. Track the objects in the transaction so you don't get
duplicate visits to the save Save() method of the same entity in the
case of a loop in your object graph.

This is no simple action, it's complex code which is likely to be
scattered all over the place, simply because you have your Save()
routine in the entity itself.
The other issue is differentiating between a "new object" and an object
being "new to the collection". In the save method for the invoice
object I must save the invoice then walk through the InvoiceItem
collection looking for "new relations" and then save the object if it
is dirty then create the relation.


It is wise to implement a Save() like method on a collection as well.
That routine simply checks if an entity is 'dirty' (or new) and calls
its Save() method.

Frans.

--
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET Blog : http://weblogs.asp.net/FBouma
Microsoft MVP (C#)
Nov 16 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3305
by: Iain Bishop | last post by:
I'm trying to model objects for the following problem: A building site contains assemblies, each of which can contain other assemblies and/or materials. I have modelled this using a Site class, Assembly class, and Material class as follows... Site Class (clsSite): Option Explicit
11
12694
by: Markus Breuer | last post by:
I have a question about oracle commit and transactions. Following scenario: Process A performs a single sql-INSERT into a table and commits the transaction. Then he informs process B (ipc) to read the new date. So process B starts "select ..." but does not get the previously inserted row. The timespan between commit and select is very short. (NOTE: two different sessions are used) Questions: 1.) Does commit when returning from call...
13
2044
by: Stephen Poley | last post by:
Good advice is frequently given in c.i.w.a.* on page structure: matters such as separation of content from presentation, graceful degradation, non-dependence on Flash etc. For some while I've wondering whether that could be transformed into a layered model: something that would help people to form a mental picture of how a complex page should be put together. I've had a go at this: http://www.xs4all.nl/~sbpoley/webmatters/pagemodel.html
0
1374
by: AMDIRT | last post by:
I have a few questions about IssueVision (from WindowsForms) concerning its scalability and performance. Rather, if I were to implement techniques described here into another application, how would it perform, how well will it scale, and what considerations should I be take into account? First, let me say that I appreciate the work done to get this application out there for me to look over. I continually refer to it and I think I am...
8
2674
by: nickdu | last post by:
I'm trying to isolate "applications" into their own application domain within a single process. I've quoted applications because it's a logical representation of an application. Basically it consists of a bunch of components supplied by some application group. I got this to work, somewhat. The problem is that the application performs roughly (and this has not been measured, but a guess based on the rendering of the application GUI) 10x...
2
1926
by: msnews.microsoft.com | last post by:
Hello, I have the scenario. I m building an application either in asp.net or window application. This application is base on n-tier application model. Let us take example of Northwind Database in SQL SERVER. i build an asp.net page. On that page i place the grid with one template column. In that column i put HTML Table with two rows. In First row there are one combobox and two textboxes. In the second row there is another DataGrid means...
3
1192
by: Paul | last post by:
Hello, I'm upgrading a small single user app to VB.NET and have a few questions about loading classes & collections classes with the data from a one to many dataset structure. I'm serializing the data to disk as a dataset and was wondering if it was an accepted practice to load/add/edit/delete the data in the dataset from methods within the collections/classes or should I just use them as a container, managing all dataset transactions...
4
1920
by: Griff | last post by:
Two questions really, the first one "conceptual" and the other more involved with design: 1 - There are two schools of thought where I work on the role of the "controller" task. The first is that the business object will provide the business rules and that the controller will implement the rules and then pass the result set to the view (i.e. do most of the grunt work).
2
1846
by: Veloz | last post by:
Hiya My question is whether or not you should associated related objects in your software using a scheme of id's and lookups, or wether objects should actually hold actual object references to objects they are associated with. For example, lets say you are modelling studen ratings of teachers. Let's say your applications needs to analyze these ratings for teachers and is provided a data file. In this data file the teachers all have...
0
8240
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8680
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8336
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8482
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6111
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4082
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4177
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2610
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1487
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.