<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Udi Dahan - The Software Simplist &#187; DataSets</title>
	<atom:link href="http://www.udidahan.com/category/datasets/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.udidahan.com</link>
	<description>Enterprise Development Expert &#38; SOA Specialist</description>
	<lastBuildDate>Sat, 24 Jul 2010 20:06:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Domain Model Pattern</title>
		<link>http://www.udidahan.com/2007/04/21/domain-model-pattern/</link>
		<comments>http://www.udidahan.com/2007/04/21/domain-model-pattern/#comments</comments>
		<pubDate>Sat, 21 Apr 2007 14:53:38 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[DataSets]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[OO]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/04/21/domain-model-pattern/</guid>
		<description><![CDATA[When implementing a domain model, often object-relational mapping technologies are used. Like many tools, with their use comes the danger of abuse &#8211; abuse to the point of invalidating the benefits of the pattern itself.
From some pointers about how to use (and not to use) these tools, see why object-relational mapping sucks.
Martin Fowler&#8217;s has this [...]]]></description>
			<content:encoded><![CDATA[<p>When implementing a domain model, often object-relational mapping technologies are used. Like many tools, with their use comes the danger of abuse &#8211; abuse to the point of invalidating the benefits of the pattern itself.</p>
<p>From some pointers about how to use (and not to use) these tools, see <a href="http://udidahan.weblogs.us/2008/06/25/object-relational-mapping-sucks/">why object-relational mapping sucks</a>.</p>
<p>Martin Fowler&#8217;s has this to say about the <a href="http://martinfowler.com/eaaCatalog/domainModel.html">Domain Model Pattern</a>:</p>
<blockquote><p>
At its worst business logic can be very complex. Rules and logic describe many different cases and slants of behavior, and it&#8217;s this complexity that objects were designed to work with. A Domain Model creates a web of interconnected objects, where each object represents some meaningful individual, whether as large as a corporation or as small as a single line on an order form.
</p></blockquote>
<p>In short, using <a href="http://udidahan.weblogs.us/category/oo/">Object-Oriented techniques</a> to handle the complexity.</p>
<p>A more comprehensive discussion about what happens when it is not used can be found under the <a href="http://www.martinfowler.com/bliki/AnemicDomainModel.html">Anemic Domain Model Anti-Pattern</a>:</p>
<blockquote><p>
The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is very little behavior on these objects. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.</p>
<p>The fundamental horror of this anti-pattern is that it&#8217;s so contrary to the basic idea of object-oriented design; which is to combine data and process together. The anemic domain model is really just a procedural style design&#8230;
</p></blockquote>
<p>In terms of <a href="http://udidahan.weblogs.us/category/ddd/">Domain-Driven Design</a>, this pattern is also known as Domain Layer.</p>
<p>Domain Models do a lot for encapsulating <a href="http://udidahan.weblogs.us/category/business-rules/">Business Rules</a>, thus making them amenable to automated testing. This hinges on keeping the Domain Model independent of things related to <a href="http://udidahan.weblogs.us/category/data-access/">Data Access</a>.</p>
<p>It is therefore almost required to use some kind of <a href="http://udidahan.weblogs.us/category/nhibernate/">Object/Relational Mapping</a> tool to make it possible to persist objects belonging to the domain model to databases and other kinds of storage.</p>
<p>The use of <a href="http://udidahan.weblogs.us/category/datasets/">DataSets</a> in .NET is often a sign of the Anemic Domain Model Anti-Pattern.</p>
<p>One thing to keep in mind when working on a domain model is that you probably won&#8217;t get it &#8220;right&#8221; the first time, and will have re-work the division of responsibility a couple of times. Techniques like <a href="http://udidahan.weblogs.us/category/tdd/">Test-Driven Development</a> help out immensely for that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/04/21/domain-model-pattern/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>[Podcast] Occasionally Connected Smart Clients and ADO.NET Sync Services</title>
		<link>http://www.udidahan.com/2007/04/17/podcast-occasionally-connected-smart-clients-and-adonet-sync-services/</link>
		<comments>http://www.udidahan.com/2007/04/17/podcast-occasionally-connected-smart-clients-and-adonet-sync-services/#comments</comments>
		<pubDate>Tue, 17 Apr 2007 21:12:15 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Ask Udi Podcast]]></category>
		<category><![CDATA[DataSets]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Smart Client]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/2007/04/17/podcast-occasionally-connected-smart-clients-and-adonet-sync-services/</guid>
		<description><![CDATA[This week&#8217;s question comes from Oran who asks:

Hi Udi, 
I&#8217;m enjoying the recent discussion on Entity Framework, disconnected clients, Unit of Work, and messaging.  A few weeks ago I wrote a note to self to &#8220;Ask Udi&#8221; about the new ADO.NET Sync Services coming out of Microsoft, and this seems to be the perfect [...]]]></description>
			<content:encoded><![CDATA[<p>This week&#8217;s question comes from Oran who asks:</p>
<blockquote><p>
Hi Udi, </p>
<p>I&#8217;m enjoying the recent discussion on <a href="http://udidahan.weblogs.us/2007/03/30/entity-framework-disconnected-problems-solutions/">Entity Framework</a>, <a href="http://udidahan.weblogs.us/2007/04/04/occasionally-connected-systems-architecture/">disconnected clients</a>, Unit of Work, and <a href="http://udidahan.weblogs.us/2007/03/31/tasks-messages-transactions-%e2%80%93-the-holy-trinity/">messaging</a>.  A few weeks ago I wrote a note to self to <a href="/ask-udi">&#8220;Ask Udi&#8221;</a> about the new ADO.NET Sync Services coming out of Microsoft, and this seems to be the perfect timing.  </p>
<p>It really seems that Sync Services is meant to address the disconnected problem raised by Andres, but it appears to be primarily targeted at enabling <a href="http://udidahan.weblogs.us/category/datasets/">DataSet</a>-centric, grid-oriented UIs, not task-oriented UIs.  They are spinning Sync Services as being an <a href="http://udidahan.weblogs.us/category/soa/">&#8220;SOA&#8221;</a> way of doing data synchronization because &#8220;it uses <a href="http://udidahan.weblogs.us/category/wcf/">WCF</a>&#8221; and &#8221; supports n-tier&#8221;.  But under the hood it&#8217;s all about DataSet-style deltas.  See Steve Lasker&#8217;s <a href="http://blogs.msdn.com/stevelasker/archive/2007/03/18/QAforOCS_2D00_SyncServicesForAdoNet.aspx">first Q&#038;A for the SOA spin</a>, and the rest of his blog for more info.</p>
<p>I&#8217;m curious what your thoughts are on the subject.  Do you see Sync Services as a valid service-oriented solution for occasionally-connected clients, or is it just another attempt by the ADO.NET team to keep us all hooked on DataSet-driven development?</p>
<p>Oran
</p></blockquote>
<p>Get it via the Dr. Dobb&#8217;s site <a href="http://ddj.com/dept/webservices/199100027">here</a>.</p>
<p>Or download directly <a href="http://www.dobbsprojects.com/media/newengine/dynamp.php/070416ud01.mp3?podcast=070416ud01.mp3">here</a>.</p>
<p><u>Additional References</u></p>
<ul>
<li><a href="http://udidahan.weblogs.us/2007/04/04/occasionally-connected-systems-architecture/">Occasionally Connected Systems Architecture</a></li>
<li><a href="http://udidahan.weblogs.us/2007/03/30/entity-framework-disconnected-problems-solutions/">Entity Framework: Disconnected Problems &#038; Solutions</a></li>
<li><a href="http://udidahan.weblogs.us/2007/03/31/tasks-messages-transactions-%e2%80%93-the-holy-trinity/">Tasks, Messages, &#038; Transactions&#8211;the holy trinity</a></li>
</ul>
<p>Want more? Go to the <a href="/ask-udi">&#8220;Ask Udi&#8221; archives</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/04/17/podcast-occasionally-connected-smart-clients-and-adonet-sync-services/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.dobbsprojects.com/media/newengine/dynamp.php/070416ud01.mp3?podcast=070416ud01.mp3" length="14630866" type="audio/mp3" />
		</item>
		<item>
		<title>[Podcast] Datasets &amp; Web Services</title>
		<link>http://www.udidahan.com/2007/03/28/podcast-datasets-web-services/</link>
		<comments>http://www.udidahan.com/2007/03/28/podcast-datasets-web-services/#comments</comments>
		<pubDate>Wed, 28 Mar 2007 20:17:27 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[Ask Udi Podcast]]></category>
		<category><![CDATA[DataSets]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://udidahan.weblogs.us/archives/435</guid>
		<description><![CDATA[This week&#8217;s question comes from Jacob who asks:

Udi,
I personally think that you could get away with datasets being the communication objects between web services in most cases even so, but I also realize that there are serious weaknesses in this approach. 
It works best if the application is confined to a single enterprise domain (like [...]]]></description>
			<content:encoded><![CDATA[<p>This week&#8217;s question comes from Jacob who asks:</p>
<blockquote><p>
Udi,</p>
<p>I personally think that you could get away with datasets being the communication objects between web services in most cases even so, but I also realize that there are serious weaknesses in this approach. </p>
<p>It works best if the application is confined to a single enterprise domain (like order processing or warehouse inventory management). Once you cross domains with your objects, you incur some serious side-effects, not least of which is that the meaning of your objects (and the operations you want to perform on them) can change with context (sometimes without you knowing it).</p>
<p>If you want an exercise in what I mean, go ask your head of marketing and your head of finance what the definition of a &#8220;sale&#8221; is&#8211;then go ask your board of directors.</p>
<p>Well, what are your thoughts?
</p></blockquote>
<p>Get it via the Dr. Dobb&#8217;s site <a href="http://ddj.com/dept/webservices/198700750">here</a>.</p>
<p>Or download directly <a href="http://www.dobbsprojects.com/media/newengine/dynamp.php/070327ud01.mp3?podcast=070327ud01.mp3">here</a>.</p>
<p>Also, take a look at <a href="http://udidahan.weblogs.us/2006/11/21/re-datasets/">how datasets affect application architecture</a>.</p>
<p>Want more? Go to the <a href="/ask-udi">“Ask Udi” archives</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2007/03/28/podcast-datasets-web-services/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://www.dobbsprojects.com/media/newengine/dynamp.php/070327ud01.mp3?podcast=070327ud01.mp3" length="11111192" type="audio/mp3" />
		</item>
		<item>
		<title>Re: Datasets</title>
		<link>http://www.udidahan.com/2006/11/21/re-datasets/</link>
		<comments>http://www.udidahan.com/2006/11/21/re-datasets/#comments</comments>
		<pubDate>Wed, 22 Nov 2006 03:14:49 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[DataSets]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://wp_630.weblogs.us/archives/354</guid>
		<description><![CDATA[Following my recent post on <a href="http://udidahan.weblogs.us/archives/037026.html">Datasets and O/R mapping</a>, I've received some comments and one in particular I wanted to call out.
<br/><br/>
Jacob Proffitt, the Rabid Paladin, wrote up <a href="http://rabidpaladin.spaces.live.com/blog/cns!9EFB431594179295!385.entry">a post on how to handle DbConcurrencyExceptions when using datasets</a>. 4 different ways, wow. I don't think that any of them would work if the same row got 2 (or more) updates before getting sent to the database, since then we'd lose the ability to implement our nice business logic in dataset internals.
<br/><br/>
The main problem that I have with datasets is how they are used. They are the answer to databinding, sending data around (the all powerful DTO), and doing online transaction processing (OLTP), and do pretty much all of them OK in the simple case. If you are building a simple system, they're probably right for you. Unfortunately, I've seen too many projects whose requirements were quite complex and got mired down so bad with datasets that they couldn't continue. And this isn't me here, who never spent the time getting good with datasets - these were people who were VERY experienced and knowledgeable in their use. 
<br/><br/>
When those same projects used different solutions for databinding/reporting, distribution, and OLTP - everything became much simpler in the common case. Complex cases that were intractable became possible.
<br/><br/>
My thanks to Jacob for making it clear how to make datasets handle common OLTP scenarios. I wonder - why didn't they make datasets do that out of the box?]]></description>
			<content:encoded><![CDATA[<p>Following my recent post on <a href="http://udidahan.weblogs.us/2006/11/09/dataset-%e2%80%93-or-mapping-rumble-at-teched-mvp-dinner/">Datasets and O/R mapping</a>, I&#8217;ve received some comments and one in particular I wanted to call out.</p>
<p>Jacob Proffitt, the Rabid Paladin, wrote up <a href="http://rabidpaladin.spaces.live.com/blog/cns!9EFB431594179295!385.entry">a post on how to handle DbConcurrencyExceptions when using datasets</a>. 4 different ways, wow. I don&#8217;t think that any of them would work if the same row got 2 (or more) updates before getting sent to the database, since then we&#8217;d lose the ability to implement our nice business logic in dataset internals.</p>
<p>The main problem that I have with datasets is how they are used. They are the answer to databinding, sending data around (the all powerful DTO), and doing online transaction processing (OLTP), and do pretty much all of them OK in the simple case. If you are building a simple system, they&#8217;re probably right for you. Unfortunately, I&#8217;ve seen too many projects whose requirements were quite complex and got mired down so bad with datasets that they couldn&#8217;t continue. And this isn&#8217;t me here, who never spent the time getting good with datasets &#8211; these were people who were VERY experienced and knowledgeable in their use. </p>
<p>When those same projects used different solutions for databinding/reporting, distribution, and OLTP &#8211; everything became much simpler in the common case. Complex cases that were intractable became possible.</p>
<p>My thanks to Jacob for making it clear how to make datasets handle common OLTP scenarios. I wonder &#8211; why didn&#8217;t they make datasets do that out of the box?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2006/11/21/re-datasets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dataset – O/R mapping rumble at TechEd MVP Dinner</title>
		<link>http://www.udidahan.com/2006/11/09/dataset-%e2%80%93-or-mapping-rumble-at-teched-mvp-dinner/</link>
		<comments>http://www.udidahan.com/2006/11/09/dataset-%e2%80%93-or-mapping-rumble-at-teched-mvp-dinner/#comments</comments>
		<pubDate>Thu, 09 Nov 2006 13:11:05 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[ADO.NET]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Business Rules]]></category>
		<category><![CDATA[Data Access]]></category>
		<category><![CDATA[DataSets]]></category>
		<category><![CDATA[NHibernate]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://wp_630.weblogs.us/archives/348</guid>
		<description><![CDATA[So, last night I was at the MVP dinner in TechEd and everything was nice. We had a nice meal, conversation was nice, weather was… nice. And then the volume started to rise, slowly at first, so as you don’t quite notice it. After a bit, you kind of stop talking and look around. And then I hear it…
<br/><br/>
&#60;WWF announcer voice&#62;<br/>
Are you ready… to RUMBLE !?!?<br/>
&#60;/WWF announcer voice&#62;<br/>
<br/>
It was datasets vs. O/R mapping, a slight twist on the infamous datasets vs. custom objects debate, all over again. They pulled me in, kicking and screaming, I swear, I really do. The lines were drawn, maintainability, performance, all the things that architects like to philosophize about in terms of other people’s work.
<br/><br/>
Anyway, I won’t give you the play-by-play ‘cause we were there almost all night. I’ll just cut to the chase.
<br/><br/>
First things first – any comparison of solutions without the context of a problem leads nowhere, fast, and stays there. So the first question I asked (when I got the chance to speak) was “are we talking about querying/reporting here?” and the answer was something like “well, yeah, but a lot of other things too”. So my suggestion was that we discuss the solutions in terms of two contexts -  querying/reporting and OLTP.
<br/><br/>
What I mean by OLTP is the data-updating kind of work that you do on certain items. Examples of this include “insert order”, “change customer address”, and “discount product”. Querying/reporting doesn’t change data, and often involves dealing with large sets of data pulled from different kinds of entities (in ERD terms).
<br/><br/>
Luckily, my suggestion to deal with them separately was accepted. Secondly, I proposed that an object model (specifically implementing the Domain Model pattern) designed for OLTP would perform poorly when used for querying/reporting – simply because it wasn’t designed for it. The structure of a domain model is such that it makes it possible to define / implement business rules in one place. That’s possible, not easy. 
<br/><br/>
Well, the dataset people weren’t going to just hand me the OLTP side of the equation without a fight, so they mentioned how easy it was to just “AcceptChanges”, and that my way was much more complex. My rebuttal came in the form of a question (are you seeing a pattern here?): Do you just swallow DbConcurrencyExceptions are do you throw all the user’s changes away when it happens? I didn’t quite make out the answer since there was a lot of mumbling going on, but I’m pretty sure they had one. I mean, you can’t develop multi-user systems using datasets without running into this situation.
<br/><br/>
The example that clinched OLTP was this. Two users perform a change to the same entity at the same time – one updates the customer’s marital status, the other changes their address. At the business level, there is no concurrency problem here. Both changes should go through. When using datasets, and those changes are bundled up with a bunch of other changes, and the whole snapshot is sent together from each user, you get a DbConcurrencyException. Like I said, I’m sure there’s a solution to it, I just haven’t heard it yet.
<br/><br/>
Now, here’s where things get interesting. I didn’t say that using a domain model automatically solves this problem. Rather, I described how each client could send a specific message, one a ChangeMaritalStatusMessage, the other a ChangeAddressMessage, to the server – in essence, giving the server the context in which each bit of data is relevant. The server could just open a transaction, get the customer object based on its Id, call a method on the customer (ChangeMaritalStatus or ChangeAddress), and commit the transaction. If two of these messages got to the server at the same time, the transactions would just cause them to be performed serially, and both transactions would succeed. The important part here is not losing the context of the changes.
<br/><br/>
When we talked about querying/reporting, things seemed quite a bit clearer. Datasets, or rather datatables seemed like a fine solution – most 3rd party controls support them out of the box. One guy mentioned that datasets performed poorly for large sets of data and that by designing custom entities for the result set, he could improve performance and memory utilization by, like, 70%. To tell you the truth, I think that if you need the performance, do it, if not, just use datasets. There isn’t much of an issue of correctness.
<br/><br/>
Just as an ending comment, in response to something someone said about scalability, I asked if they were reporting against the live OLTP data. The response was “yes”. Well, there’s a database scalability problem if I ever saw one. OLTP works most correctly when employing transactions that have an isolation level of serializable. The problem with them is that they lock up the whole table, or get blocked when a table scan is going on. Querying often results in a table scan. You can see the problem. Anyway, a common solution to this problem is to just reduce the isolation level, a quick fix that improves performance almost immediately. You take one hit in that your reports may be showing incorrect data, especially if they do aggregate type work. You might take another hit if your OLTP transactions need to do aggregate type work themselves. That second hit is pretty much unacceptable. A different solution is to accept the fact that the heaviest querying can usually show data that isn’t up to date up to the second.
<br/><br/>
In such a solution, you would have another database for reporting. It wouldn’t be just a replica of the OLTP database, but rather a lot more denormalized – which is a really not nice way of saying designed for reporting. You could then move the data from your OLTP database to the reporting database in some way (more to come on this topic) and you increase the scalability of your database. Just to define that a bit better – your OLTP database will be able to handle more transactions per unit of time, and reports will run faster, meaning that you will both improve their latency and the number of queries that can be handled per unit of time.
<br/><br/>
Anyway, I was pretty tired after all that, but if I had to sum it up I’d say something like this: before debating solutions, define the problem, you get a lot more insight into the solutions and you get it faster. That’s just win-win all around.]]></description>
			<content:encoded><![CDATA[<p>So, last night I was at the MVP dinner in TechEd and everything was nice. We had a nice meal, conversation was nice, weather was… nice. And then the volume started to rise, slowly at first, so as you don’t quite notice it. After a bit, you kind of stop talking and look around. And then I hear it…</p>
<p>&lt;WWF announcer voice&gt;<br />
Are you ready… to RUMBLE !?!?<br />
&lt;/WWF announcer voice&gt;</p>
<p>It was <a href="http://udidahan.weblogs.us/category/datasets/">Datasets</a> vs. <a href="http://udidahan.weblogs.us/category/nhibernate/">O/R mapping</a>, a slight twist on the infamous datasets vs. custom objects debate, all over again. They pulled me in, kicking and screaming, I swear, I really do. The lines were drawn, maintainability, performance, all the things that architects like to philosophize about in terms of other people’s work.</p>
<p>Anyway, I won’t give you the play-by-play ‘cause we were there almost all night. I’ll just cut to the chase.</p>
<p>First things first – any comparison of solutions without the context of a problem leads nowhere, fast, and stays there. So the first question I asked (when I got the chance to speak) was “are we talking about querying/reporting here?” and the answer was something like “well, yeah, but a lot of other things too”. So my suggestion was that we discuss the solutions in terms of two contexts &#8211;  querying/reporting and OLTP.</p>
<p>What I mean by OLTP is the data-updating kind of work that you do on certain items. Examples of this include “insert order”, “change customer address”, and “discount product”. Querying/reporting doesn’t change data, and often involves dealing with large sets of data pulled from different kinds of entities (in ERD terms).</p>
<p>Luckily, my suggestion to deal with them separately was accepted. Secondly, I proposed that an object model (specifically implementing the <a href="http://udidahan.weblogs.us/2007/04/21/domain-model-pattern/">Domain Model pattern</a>) designed for OLTP would perform poorly when used for querying/reporting – simply because it wasn’t designed for it. The structure of a domain model is such that it makes it possible to define / implement <a href="http://udidahan.weblogs.us/category/business-rules/">business rules</a> in one place. That’s possible, not easy. </p>
<p>Well, the dataset people weren’t going to just hand me the OLTP side of the equation without a fight, so they mentioned how easy it was to just “AcceptChanges”, and that my way was much more complex. My rebuttal came in the form of a question (are you seeing a pattern here?): Do you just swallow DbConcurrencyExceptions are do you throw all the user’s changes away when it happens? I didn’t quite make out the answer since there was a lot of mumbling going on, but I’m pretty sure they had one. I mean, you can’t develop multi-user systems using datasets without running into this situation.</p>
<p>The example that clinched OLTP was this. Two users perform a change to the same entity at the same time – one updates the customer’s marital status, the other changes their address. At the business level, there is no <a href="http://udidahan.weblogs.us/2007/01/22/realistic-concurrency/">concurrency</a> problem here. Both changes should go through. When using datasets, and those changes are bundled up with a bunch of other changes, and the whole snapshot is sent together from each user, you get a DbConcurrencyException. Like I said, I’m sure there’s a solution to it, I just haven’t heard it yet.</p>
<p>Now, here’s where things get interesting. I didn’t say that using a domain model automatically solves this problem. Rather, I described how each client could send a specific message, one a ChangeMaritalStatusMessage, the other a ChangeAddressMessage, to the server – in essence, giving the server the context in which each bit of data is relevant. The server could just open a transaction, get the customer object based on its Id, call a method on the customer (ChangeMaritalStatus or ChangeAddress), and commit the transaction. If two of these messages got to the server at the same time, the transactions would just cause them to be performed serially, and both transactions would succeed. The important part here is not losing the context of the changes.</p>
<p>When we talked about querying/reporting, things seemed quite a bit clearer. Datasets, or rather datatables seemed like a fine solution – most 3rd party controls support them out of the box. One guy mentioned that datasets performed poorly for large sets of data and that by designing custom entities for the result set, he could improve performance and memory utilization by, like, 70%. To tell you the truth, I think that if you need the performance, do it, if not, just use datasets. There isn’t much of an issue of correctness.</p>
<p>Just as an ending comment, in response to something someone said about <a href="http://udidahan.weblogs.us/category/scalability/">scalability</a>, I asked if they were reporting against the live OLTP data. The response was “yes”. Well, there’s a database scalability problem if I ever saw one. OLTP works most correctly when employing transactions that have an isolation level of serializable. The problem with them is that they lock up the whole table, or get blocked when a table scan is going on. Querying often results in a table scan. You can see the problem. Anyway, a common solution to this problem is to just reduce the isolation level, a quick fix that improves performance almost immediately. You take one hit in that your reports may be showing incorrect data, especially if they do aggregate type work. You might take another hit if your OLTP transactions need to do aggregate type work themselves. That second hit is pretty much unacceptable. A different solution is to accept the fact that the heaviest querying can usually show data that isn’t up to date up to the second.</p>
<p>In such a solution, you would have another database for reporting. It wouldn’t be just a replica of the OLTP database, but rather a lot more denormalized – which is a really not nice way of saying designed for reporting. You could then move the data from your OLTP database to the reporting database in some way (more to come on this topic) and you increase the scalability of your database. Just to define that a bit better – your OLTP database will be able to handle more transactions per unit of time, and reports will run faster, meaning that you will both improve their latency and the number of queries that can be handled per unit of time.</p>
<p>Anyway, I was pretty tired after all that, but if I had to sum it up I’d say something like this: before debating solutions, define the problem, you get a lot more insight into the solutions and you get it faster. That’s just win-win all around.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2006/11/09/dataset-%e2%80%93-or-mapping-rumble-at-teched-mvp-dinner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code from First Agile Israel Meeting</title>
		<link>http://www.udidahan.com/2005/02/01/code-from-first-agile-israel-meeting/</link>
		<comments>http://www.udidahan.com/2005/02/01/code-from-first-agile-israel-meeting/#comments</comments>
		<pubDate>Wed, 02 Feb 2005 02:59:00 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[DataSets]]></category>
		<category><![CDATA[NHibernate]]></category>

		<guid isPermaLink="false">http://wp_630.weblogs.us/archives/168</guid>
		<description><![CDATA[The code I presented at the Agile Israel meeting can be downloaded here. It&#8217;s just a small sampling of how much code you DON&#8217;T have to write when using O/R Mapping.
]]></description>
			<content:encoded><![CDATA[<p>The code I presented at the Agile Israel meeting can be downloaded <a href="http://udidahan.weblogs.us/archives/NHibernate demo.zip">here</a>. It&#8217;s just a small sampling of how much code you DON&#8217;T have to write when using O/R Mapping.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2005/02/01/code-from-first-agile-israel-meeting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code breaks, automated code breaks automatically</title>
		<link>http://www.udidahan.com/2004/04/13/code-breaks-automated-code-breaks-automatically/</link>
		<comments>http://www.udidahan.com/2004/04/13/code-breaks-automated-code-breaks-automatically/#comments</comments>
		<pubDate>Wed, 14 Apr 2004 03:56:32 +0000</pubDate>
		<dc:creator>thesoftwaresimplist</dc:creator>
				<category><![CDATA[DataSets]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://wp_630.weblogs.us/archives/57</guid>
		<description><![CDATA[<p>
The <a href="http://www.lazycoder.com/weblog/index.php">lazycoder</a> puts up <a href="http://www.lazycoder.com/weblog/index.php?p=51">his take</a> on the whole <a href="http://objectsharp.com/Blogs/barry/archive/2004/02/10/273.aspx">custom classes versus datasets ( et al ) debate</a>. He draws the line on making strongly typed collections, for no other reason than performance - rather, performance pertaining to the amount of memory utilization.
</p><p>
The true fact of the matter is that the memory overhead you pay for using strongly typed collections is quite small. 900 Customer objects in a CustomerCollection is the same order ( as in big-O notation ) as 900 datarows in a datatable. If anything, your ability to control the memory utilization is greater when using the CustomerCollection since you control the footprint of each Customer. You have much less control over the memory footprint of the datarow.
</p><p>
So, if memory utilization is better with strongly typed collections ( or even the same assuming a common case ), memory utilization does not appear to be a valid concern for choosing datasets &#038; co over strongly typed collections.
</p><p>
Development time is a valid concern, and is brought up quite often. From my experience, it does take less time to use datasets to get to the 80% functionality mark. However, that last 20% becomes that much harder because the ability to control datasets' behaviour is quite diminished. Thus, over the entire development lifecycle, I find that strongly typed everything works in my best interests.
</p><p>
One final note - I'm not against auto-generated code. Quite the opposite, really. I try to automate any parts of the development process that I can. However, I am against relying on code generated by something not under my control, and am dead set against not understanding how that code works. Code breaks, automated code breaks automatically.
</p>]]></description>
			<content:encoded><![CDATA[<p><P>The <A href="http://www.lazycoder.com/weblog/index.php">lazycoder </A>puts up <A href="http://www.lazycoder.com/weblog/index.php?p=51">his take </A>on the whole <A href="http://objectsharp.com/Blogs/barry/archive/2004/02/10/273.aspx">custom classes versus datasets ( et al ) debate</A>. He draws the line on making strongly typed collections, for no other reason than performance &#8211; rather, performance pertaining to the amount of memory utilization.</P><br />
<P>The true fact of the matter is that the memory overhead you pay for using strongly typed collections is quite small. 900&nbsp;Customer objects in a CustomerCollection is the same order ( as in big-O notation ) as 900 datarows in a datatable. If anything, your ability to control the memory utilization is greater when using the CustomerCollection since you control the footprint of each Customer. You have much less control over the memory footprint of the datarow.</P><br />
<P>So, if memory utilization is better with strongly typed collections ( or even the same assuming a common case ), memory utilization does not appear to be a valid concern for choosing datasets &amp; co over strongly typed collections.</P><br />
<P>Development time is a valid concern, and is brought up quite often. From my experience, it <EM>does</EM> take less time to use datasets to get to the 80% functionality mark. However, that last 20% becomes that much harder because the ability to control datasets&#8217; behaviour is quite diminished. Thus, over the entire development lifecycle, I find that strongly typed <EM>everything</EM> works in my best interests.</P><br />
<P>One final note &#8211; I&#8217;m not against auto-generated code. Quite the opposite, really. I try to automate any parts of the development process that I can. However, I am against relying on code generated by something not under my control, and am <EM>dead</EM> set against not understanding how that code works. Code breaks, automated code breaks automatically.</P></p>
]]></content:encoded>
			<wfw:commentRss>http://www.udidahan.com/2004/04/13/code-breaks-automated-code-breaks-automatically/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
