[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.inetserver.asp.db

コーチショルダー バッグ

cc_crash

12/28/2013 3:49:00 PM

<a href=http://www.mollymcginness.com/airjordanfi.h... Jordan 5 3m</a>
&#12467;&#12540;&#12481; &#12509;&#12540;&#12481;}
<a href=http://www.mollymcginness.com/airjordanfi.h... Jordan Suomi</a>
11 Answers

Jonathan Wood

11/29/2007 2:59:00 AM

0

Scott,

> This is what ADO .NET is all about (disconnected access to your data).
> Test after test and benchmark after benchmark have shown it to be a more
> efficient way of modeling the entire application than the older connected
> ways of ADO. When dealing with large amounts of data (1,000's of
> records), you don't grab and store it all at once, you make several trips
> to the database, fetching the data you happen to need at that time
> (perhaps hundreds of records on each call). This just isn't the issue
> that you think it is.

Well, I'm not certain what you think I think it is. Obviously, Microsoft
thought it worthwhile to create a DataReader class.

> A DataAdapter is really a form of composite class. It uses information
> from your connection in conjunction with 4 child command objects to
> perform your CRUD actions against the database. In the case of a read
> operation, it turns out that a DataAdapter uses a DataReader internally to
> iterate through the data and copy it to a DataTable so that the connection
> can then be closed and the data can be used in memory only.

So we're comparing using a DataReader with using a DataReader *AND* a
DataSet? Why wouldn't I think using just one of them would be more efficient
(assuming I am not changing the data)?

> Public Class DataLayer
> Dim con As New
> SQLClient.SQLConnection(ConfigurationManager.ConnectionStrings("ASPNETDB").ToString())
>
> Public Function GetProductData() As DataSet
> Dim cmd As New SQLClient.SQLCommand(con)
> cmd.CommandType = StoredProcedure
> cmd.CommandText = "storedProcName"
> Dim da As new SQLCLient.SQLDataAdapter(cmd, con)
> Dim ds As New DataSet()
> Try
> da.Fill(ds)
> Catch e As SQLClient.SQLException
> 'DataBase thrown exception handling here
>
> Catch e As Exception
> 'All other exceptions handled here
>
> Finally
> 'A DataAdapter will close the connection for you, but if there
> was an
> 'exception before it gets the chance this will cover us and it
> won't cause
> 'any problems if the connection has already been closed.
> con.close()
> con.Dispose()
> End Try
>
> Return ds
> End Function
>
> End Class

I appreciate that but, as expected, this raises questions for me.

You retrieve a connection string, allocate an SQLConnection object, allocate
several other objects, and I'm suspecting that the call to the
SqlDataAdapter constructor even connects to the database. And all of that
occurs outside of any exception handling. I realized these errors may be
unlikely, but if being "rock solid" was the goal, wouldn't they be wrapped
in a try statement?

I know that part of this is that I don't know, for example, exactly what the
SqlDataAdapter constructor does. But I'm guessing some of the items
mentioned above could potentially raise an exception.

> Within this data layer class, you could add other methods for doing other
> CRUD related operations, each method reusing the connection object. This
> is a good example of abstracting data logic from business logic as well.

Yes, that's the approach I'm trying to take.

> As to non-deterministic finalization, I don't see why you think this
> breaks encapsulation. "When" the object is cleaned up does not have
> anything to do with object's functionality being encapsulated within it.
> After all, we aren't doing any database cleanup in the Finalize method,
> nor the Dispose method. These methods simply prepare the object for
> destruction, but even still their functionality is encapsulated within the
> object.

I don't believe I said it "breaks" encapsulation, it reduces it. The reason
encapsulation is considered a good thing, is because it means you only have
to understand an objects public interface in order to use it. But, here, you
really need to know something more about it's implementation because you
must know whether or not it must be disposed. I never had to even think
about that in languages like C++.

I can see we won't agree on all these issues but I appreciate your input.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Jonathan Wood

11/29/2007 4:28:00 AM

0

Scott,

> I think you are comparing apples and watermelons here. Just using a
> DataReader (as you did) will allocate less memory on the heap, but because
> you've got to keep your DataReader open while you want to see the data,
> you end up with your initial problem you posted about and you tie up
> resources on the DataBase longer than needed.

Yes, I understand what you are saying, and that there are trade offs. I'm
only just studying how to use data objects to avoid loading entire result
sets in the ASP.NET list controls and instead loading part at a time.

> Using the DataSet/DataAdapter approach you allocate more resources in the
> heap, but tie up less database resources. And, the amount of memory
> allocated for a DataAdapter is inconsequential (it doesn't store any data
> within it). RAM is cheap these days and the GC will manage our heap
> resources for us. This is the part I think you are putting to much
> emphasis on. Sure, as programmers we don't want to waste resources like
> RAM, but on the other hand we have these classes that have been optimized
> for the jobs they do and they do them well. Couple that with the .NET
> Framework managing memory for us on another thread and it (as I said
> before) is not really impactfull on the application.

> No, the connection doesn't occur until the DataAdapter fires its Fill()
> method.

Okay, that's good to know.

> The only thing that *could* cause an exception is the call for the
> connection string (if the string didn't exist in the web.config file).
> The declaration/instantiation of the other objects would not/could not
> fail (allocating memory for a DataAdapter isn't going to fail under any
> circumstance, for example.

Eh? You're saying New could never fail under any circumstance?

> You'd need to use it improperly for it to fail and that's why my Try
> doesn't begin until I'm actually using the DA). The connection is not
> opened until the DataAdapter calls it's Fill method, hence that's where my
> try statement begins. But, if you are still worried, just move the Try up
> to just after the Sub begins, but it's really not necessary. And, if you
> did move the opening Try up further, then what's the problem?

Then the Finally block could fail if you attempt to close and dispose of
objects that have not yet been allocated.

>>> Within this data layer class, you could add other methods for doing
>>> other CRUD related operations, each method reusing the connection
>>> object. This is a good example of abstracting data logic from business
>>> logic as well.
>>
>> Yes, that's the approach I'm trying to take.
>>
>>> As to non-deterministic finalization, I don't see why you think this
>>> breaks encapsulation. "When" the object is cleaned up does not have
>>> anything to do with object's functionality being encapsulated within it.
>>> After all, we aren't doing any database cleanup in the Finalize method,
>>> nor the Dispose method. These methods simply prepare the object for
>>> destruction, but even still their functionality is encapsulated within
>>> the object.
>>
>> I don't believe I said it "breaks" encapsulation, it reduces it. The
>> reason encapsulation is considered a good thing, is because it means you
>> only have to understand an objects public interface in order to use it.
>> But, here, you really need to know something more about it's
>> implementation because you must know whether or not it must be disposed.
>> I never had to even think about that in languages like C++.
>
> Perhaps, but if it is a reduction, I think it's very minor. But, you did
> have to destroy your object references in C++, which really is more of a
> maintenance task that is not related to the purpose of the code you were
> writing. By having Garbage Collection, I think we get to a more pure way
> of building classes, because we only have to worry about the business
> logic that class should perform and we can let the .NET Framework do the
> menial management of the details.

It's a trade-off. But most C++ objects are declared on the stack. These
don't need to be manually deleted or disposed, and I don't need to know
anything about what the destructor does. I'm having a hard time with this.

> I do understand the points you are making and when I started with .NET in
> 2001, I had many of the same concerns. But reading the white papers and
> writing the applications has shown me that using a disconnected data model
> is a much better way to go and that non-deterministic finalization is also
> a much more memory efficient and less labor intensive way of working.

I'm trying to understand as much of what you say as possible. As always,
software development is a system of trade offs. Although I first looked at
..NET back when it was new, I haven't been able to seriously dedicate myself
to it until now. With HTML, CSS, ASP.NET, ADO.NET, SQL, stored procedures,
C#, etc., etc., it's got to be one of the hardest changes I've made. I've
always been a careful programmer, and I know a big part of the problem for
me is knowing which constructs are best because I don't yet fully know
enough about what the underlying methods are doing.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Jonathan Wood

11/30/2007 5:37:00 PM

0

Scott,

>> Eh? You're saying New could never fail under any circumstance?
>
> That's correct.

Any possibility you could elaborate? Or point me to additional info? What if
you run out of memory?

> As I say, a connection instantiation could fail if the connection string
> referenced in the constructor argument can't be resolved.
> But, a DataAdapter instantiation will never fail, as no actions are
> performed as a result of its instantiation, just configuration is
> performed.
> Likewise for a Command object, a DataSet, a DataTable, and many many more.

I have been rolling this issue around in my mind since we've been discussing
this. The more I think about it, some of these errors would indicate a
serious problem with the site, to the point where recovery may not even be
desirable. The case where it's most important to dispose of objects to free
resources is when the site is running without error. So my thinking may be
changing a bit on that.

>> It's a trade-off. But most C++ objects are declared on the stack. These
>> don't need to be manually deleted or disposed, and I don't need to know
>> anything about what the destructor does. I'm having a hard time with
>> this.
>
> You don't need to know anything about them here either because, although
> we have .Dispose and .Finalize, we don't have destructors, per se in a GC
> environment.

Here, I strongly disagree. I need to know if the object allocates resources
in a manner that needs to be disposed, and call Dispose if that is the case.
That was the point of my paragraph above. This requires me to know more
about what the object does in order to use it correctly.

> Finalize isn't going to (and shouldn't) have destructor-type code in it
> because we don't know when (or if) the object is going to be collected.

We don't know when. I'm not sure why you say we don't know *if*.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Scott M.

12/2/2007 6:37:00 AM

0


"Jonathan Wood" <jwood@softcircuits.com> wrote in message
news:%23zTDce3MIHA.536@TK2MSFTNGP06.phx.gbl...
> Scott,
>
>>> Eh? You're saying New could never fail under any circumstance?
>>
>> That's correct.
>
> Any possibility you could elaborate? Or point me to additional info? What
> if you run out of memory?

Ok, well if we're going to think in those terms, then every variable that we
ever use should be in a try catch. Or, we could work in an environment
where memory is managed for us by a autonomous black box that monitors
memory and throws away what we don't need when we would need it to...Wait a
moment....we've got that.

If we were to run out of memory by simply allocating such a small amount of
memory needed for any of the objects we've been discussing then, it would
most likely not be because of the program we were writing - something else
would be the culprit (something unmanaged), in which case no matter what we
do in our program would really matter.

> As I say, a connection instantiation could fail if the connection string
>> referenced in the constructor argument can't be resolved.
>> But, a DataAdapter instantiation will never fail, as no actions are
>> performed as a result of its instantiation, just configuration is
>> performed.
>> Likewise for a Command object, a DataSet, a DataTable, and many many
>> more.
>
> I have been rolling this issue around in my mind since we've been
> discussing this. The more I think about it, some of these errors would
> indicate a serious problem with the site, to the point where recovery may
> not even be desirable. The case where it's most important to dispose of
> objects to free resources is when the site is running without error. So my
> thinking may be changing a bit on that.

Some of what errors? As I say, you'r not going to get errors from
instantiating these objects using correct syntax.

>
>>> It's a trade-off. But most C++ objects are declared on the stack. These
>>> don't need to be manually deleted or disposed, and I don't need to know
>>> anything about what the destructor does. I'm having a hard time with
>>> this.
>>
>> You don't need to know anything about them here either because, although
>> we have .Dispose and .Finalize, we don't have destructors, per se in a GC
>> environment.
>
> Here, I strongly disagree. I need to know if the object allocates
> resources in a manner that needs to be disposed, and call Dispose if that
> is the case. That was the point of my paragraph above. This requires me to
> know more about what the object does in order to use it correctly.

Not all objects have a dispose method. If the object has a dispose method,
it is an indication to you that calling dispose may be necessary. But, as
with any object, you do need to know something about its general behavior.
In the case of the Command object (that I initially mentioned you don't have
to worry about disposing), you don't need to dispose it because you should
explicitly close your DataReader (which is the real hook into the database).
By calling the ExecuteReader method of the Command object, you are
implicitly opening the DataReader and in ADO .NET, anything that can be
opened is going to expose a .close() method, which should be called. Again,
this does not break encapsulation, because we don't need to know or
understand what happens when we call close, the object's interface gives us
the clue as to how to use it. When the DataReader object's interface is
examined closely, it becomes apparent that it is the object using the
unmanged resource, not the connection that spawned/returned it and once we
know that, we know we don't need to call the command object's Dispose
method. Again, this is not a violation of encapsulation, it's information
we get from examining the interface. Just like knowing not to call or worry
about dispose on the many objects that don't have such a member. If there
is no dispose method, then the interface gives us a clue as to inner
workings of the object. Encapsulation doesn't mean that we don't have to
know anything about an object in order to use it correctly. It says we
don't have to be concerned with how the object does what it does internally,
but we do need to know and understand the interface.

>
>> Finalize isn't going to (and shouldn't) have destructor-type code in it
>> because we don't know when (or if) the object is going to be collected.
>
> We don't know when. I'm not sure why you say we don't know *if*.

No, we don't know *if* an object will be finalized. If we have a 24/7 app.,
running on a powerful server, with ample resources, then theoretically, an
ojbect could sit on the heap indefinately becaue the GC doesn't collect
garbarge at regular inervals, it collects when it needs to collect. If
there is no need, then the objects sit on the heap and don't get finalized.
This is why we don't put clean up code in the finalizer and why finalziers
in .NET are not the same thing as destructors in C/C++.


>
> --
> Jonathan Wood
> SoftCircuits Programming
> http://www.softci...
>

Jonathan Wood

12/3/2007 9:02:00 PM

0

Scott,

>> Any possibility you could elaborate? Or point me to additional info? What
>> if you run out of memory?
>
> Ok, well if we're going to think in those terms, then every variable that
> we ever use should be in a try catch. Or, we could work in an environment
> where memory is managed for us by a autonomous black box that monitors
> memory and throws away what we don't need when we would need it to...Wait
> a moment....we've got that.

How does the second part of that address the first part? If we can run out
of memory, we could get an error. Unless I'm missing something, the only
question that remains is whether or not we want to catch and respond to such
errors. I'm not getting how GC changes that.

> Some of what errors? As I say, you'r not going to get errors from
> instantiating these objects using correct syntax.

I thought you just got through agreeing with me that, in fact, it is
possible to get such errors.

Nevermind. I was addressing a larger issue and then we went backwards.

> Not all objects have a dispose method. If the object has a dispose
> method, it is an indication to you that calling dispose may be necessary.
> But, as with any object, you do need to know something about its general
> behavior.

I thought I just pointed out how this is not the case with C++ objects.

Oh well.

> In the case of the Command object (that I initially mentioned you don't
> have to worry about disposing), you don't need to dispose it because you
> should explicitly close your DataReader (which is the real hook into the
> database).

And there you have it. That fact that the Command object has a Dispose
method is not enough information. You really need to know even more about
how these objects work. This is exactly the point I've been trying to make.

At any rate, I appreciate your input. But there's not much point in trying
to reach agreement on all these issues.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Scott M.

12/5/2007 5:00:00 AM

0


"Jonathan Wood" <jwood@softcircuits.com> wrote in message
news:utXEO$eNIHA.280@TK2MSFTNGP03.phx.gbl...
> Scott,
>
>>> Any possibility you could elaborate? Or point me to additional info?
>>> What if you run out of memory?
>>
>> Ok, well if we're going to think in those terms, then every variable that
>> we ever use should be in a try catch. Or, we could work in an
>> environment where memory is managed for us by a autonomous black box that
>> monitors memory and throws away what we don't need when we would need it
>> to...Wait a moment....we've got that.
>
> How does the second part of that address the first part? If we can run out
> of memory, we could get an error. Unless I'm missing something, the only
> question that remains is whether or not we want to catch and respond to
> such errors. I'm not getting how GC changes that.

But, my point is that we would NOT run out of memory like is possible in
C++. We have a Garbage Collector and its job is to ensure that we don't run
out of memory. That's why we don't have to worry about simply instantiating
an object causing us to run out of memory. Since running out of memory is
not going to happen as a result of instantiating an object, there's no need
to wrap instantiations that do not execute operations in any kind of
Try..Catch.

>> Some of what errors? As I say, you'r not going to get errors from
>> instantiating these objects using correct syntax.
>
> I thought you just got through agreeing with me that, in fact, it is
> possible to get such errors.

No, I was making the point that because we work in an environment that has a
GC, this is not an issue that requires us to waste any brain power on it.

>
> Nevermind. I was addressing a larger issue and then we went backwards.
>
>> Not all objects have a dispose method. If the object has a dispose
>> method, it is an indication to you that calling dispose may be necessary.
>> But, as with any object, you do need to know something about its general
>> behavior.
>
> I thought I just pointed out how this is not the case with C++ objects.

Maybe, but my point is that this isn't C++. It is a managed environment.
Because C/C++ developers have historically worked at a much lower level than
other languages, they are used to having to worry about managing machine
resources themselves manually. In .NET, these tasks become trivial to the
developer. We let the CLR take care of such things. It's ok to do so
because the managed environment of the CLR manages these duties very well.
I think this is really the issue you are facing here. You are having
trouble letting go of the chores of the C++ programmer and embrace that in
..NET we work a bit differently.

>
> Oh well.
>
>> In the case of the Command object (that I initially mentioned you don't
>> have to worry about disposing), you don't need to dispose it because you
>> should explicitly close your DataReader (which is the real hook into the
>> database).
>
> And there you have it. That fact that the Command object has a Dispose
> method is not enough information. You really need to know even more about
> how these objects work. This is exactly the point I've been trying to
> make.

Well, you've said that this breaks encapsulation and I disagree with that.
Of course we have to learn about the classes we intend to use. We do not
need to know about the internal workings of the class, we just need to
examine the interfaces of the classes involved.

>
> At any rate, I appreciate your input. But there's not much point in trying
> to reach agreement on all these issues.

Good luck Jonathan!

>
> --
> Jonathan Wood
> SoftCircuits Programming
> http://www.softci...
>

Jonathan Wood

12/5/2007 5:45:00 AM

0

Scott,

> But, my point is that we would NOT run out of memory like is possible in
> C++. We have a Garbage Collector and its job is to ensure that we don't
> run out of memory.

GC will optimize the heap, which prolongs running out of memory as long as
possible. I'm sorry, but you are mistaken if you think GC can prevent
running out of memory.

>> And there you have it. That fact that the Command object has a Dispose
>> method is not enough information. You really need to know even more about
>> how these objects work. This is exactly the point I've been trying to
>> make.
>
> Well, you've said that this breaks encapsulation and I disagree with that.
> Of course we have to learn about the classes we intend to use. We do not
> need to know about the internal workings of the class, we just need to
> examine the interfaces of the classes involved.

I just got through describing that the very example you gave shows that we
not only need to know something about whether or not the class maintains
resources that must be cleaned up, but now we also need to know about which
classes might clean up other classes. I don't know how you define
encapsulation but to me it's about only needing to understand a class's
interface to use it, and not anything about it's implementation. That's more
than one clear example of how the lack of DF is a step in the other
direction.

Again, I understand you may never agree to this but I've been doing this
long enough to understand the benefits of OOP and encapsulation. And, here,
learning this stuff is harder because I am not gaining all the traditional
benefits of OOP and encapsulation.

It's just my opinion. YMMV.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Scott M.

12/6/2007 3:32:00 AM

0


"Jonathan Wood" <jwood@softcircuits.com> wrote in message
news:eqjS8HwNIHA.4880@TK2MSFTNGP03.phx.gbl...
> Scott,
>
>> But, my point is that we would NOT run out of memory like is possible in
>> C++. We have a Garbage Collector and its job is to ensure that we don't
>> run out of memory.
>
> GC will optimize the heap, which prolongs running out of memory as long as
> possible. I'm sorry, but you are mistaken if you think GC can prevent
> running out of memory.

GC does more than optimize the heap, it "manages" the heap and makes
decisions about "when" and "if" objects need to be destroyed. To say that
the GC can't prevent us from running out of memory is incorrect. It most
certainly can and does.

>
>>> And there you have it. That fact that the Command object has a Dispose
>>> method is not enough information. You really need to know even more
>>> about how these objects work. This is exactly the point I've been trying
>>> to make.
>>
>> Well, you've said that this breaks encapsulation and I disagree with
>> that. Of course we have to learn about the classes we intend to use. We
>> do not need to know about the internal workings of the class, we just
>> need to examine the interfaces of the classes involved.
>
> I just got through describing that the very example you gave shows that we
> not only need to know something about whether or not the class maintains
> resources that must be cleaned up, but now we also need to know about
> which classes might clean up other classes. I don't know how you define
> encapsulation but to me it's about only needing to understand a class's
> interface to use it, and not anything about it's implementation. That's
> more than one clear example of how the lack of DF is a step in the other
> direction.

And, I've said that we learn what we need to know from the interfaces of the
objects involved. We do not need to know how they do what they do. You
most certainly *can* call dispose on your Command object, but in the
scenario you've shown, it is unneccessary. I do not believe that having a
basic understanding of the nuances of a class so that I can use them more
effectively breaks encapsulation.

>
> Again, I understand you may never agree to this but I've been doing this
> long enough to understand the benefits of OOP and encapsulation. And,
> here, learning this stuff is harder because I am not gaining all the
> traditional benefits of OOP and encapsulation.
>
> It's just my opinion. YMMV.

Ah, but I've been doing this long enough (from this side of the fence) to
understand the benefits of OOP in a managed environment. As a matter of
fact, I am a technology trainer and have been teaching .NET since its
inception. I have encountered many folks, just like yourself (comming to
..NET from a lower-level programming language like C/C++) and, over and over
seen that, for these folks, the switch to this managed framework can be
difficult due to the additional burdens the C/C++ environment places on
developers, but how used to it they get and how they are reluctant to give
it up as they move into .NET. There really much, in the way of OO benefits,
that you are losing here.

What if I had just told you to call dispose on any object that has such a
method and that this would be sufficient to cause the object to clean up
appropriately? That would put your whole argument about encapsulation to
rest, wouldn't it? Because if you choose to code by that rule, it will not
cause you *any* troubles in any situation you encounter, ever. You can code
this way, feel good about encapsulation and not feel that you've lost
anything. But, it just happens that a command object has a dispose method
because it inherits from the component class (which exposes such a method)
and that Microsoft puts a dispose method on the component class for the
benefit of the many subclasses in the framework that do *need* this
functionality. It just turns out that the command object doesn't. Now, you
know that encapsulation says the we do not *need* to know about an object's
implementation in order to use it and I still maintain that is true here. I
could have never mentioned anything about Dispose and your code would
function exactly as it needs to. But, you can't tell me that *if* I happen
to know something about an object's implementation, that I wouldn't be able
to write code for it in a more optmized way. That is not what encapsulation
says. I still maintain that we have full encapsulation here.

I really think that you should do a little more research on the GC, which
will show you that it does, in fact, protect us from memory leaks and
outages, which makes much of what you have been inquiring about (where to
use Try...Catch and creating "bullet-proof" non-crashable code), not an
issue in all but extreme coding scenarios or poorly designed hardware
architectures. There's no such thing as "bullet-proof" or "uncrashable"
code in any lanaguge. No, I can't make you that guarantee. But I can tell
you that for very nearly 100% of situations, running out of memory due to
simply instantiating an object won't or can't cause us to run out of memory.
In the extremely rare scenarios where it might, we'd most likely to
attribute the cause to either unmanaged resources not being properly used or
very poorly written managed code. But, hey, you can write bad code in any
language.

As for your original concern about persisting a copy of the data in a
DataSet, again I'll refer you to more research on the GC, the DataSet and
DataTable classes, and the overhead of keeping an active database "hook"
longer than is really needed.

-Scott

Jonathan Wood

12/6/2007 6:05:00 AM

0

Scott,

> GC does more than optimize the heap, it "manages" the heap and makes
> decisions about "when" and "if" objects need to be destroyed.

That process of destroying objects as well as rearranging memory is what I
meant by optimize.

> To say that the GC can't prevent us from running out of memory is
> incorrect. It most certainly can and does.

It may be that the chances you'll run out of memory are exceedingly low, but
to suggest GC prevents us from doing so makes no sense. If you still
disagree, have a look at what MS says about the new operator allocating
memory in C#:

"If the new operator fails to allocate memory, it throws the exception
OutOfMemoryException."
http://msdn2.microsoft.com/en-us/librar...(VS.71).aspx

Obviously, there is only so much memory. How can GC prevent us from running
out?

> scenario you've shown, it is unneccessary. I do not believe that having a
> basic understanding of the nuances of a class so that I can use them more
> effectively breaks encapsulation.

Then we apparently have different working definitons of "encapsulation."

> Ah, but I've been doing this long enough (from this side of the fence) to
> understand the benefits of OOP in a managed environment.

The principles and benefits of OOP have not changed just because OOP has
been implemented in a managed environment.

> What if I had just told you to call dispose on any object that has such a
> method and that this would be sufficient to cause the object to clean up
> appropriately? That would put your whole argument about encapsulation to
> rest, wouldn't it? Because if you choose to code by that rule, it will not
> cause you *any* troubles in any situation you encounter, ever.

It could affect performance and, no matter how easy the IDE makes it to
determine whether or not a class implements Dispose, it still must be known
and so it supports my position.

> I really think that you should do a little more research on the GC

Perhaps you can point out one aspect of GC that I have demonstrated I do not
understand. I have discussed these issues at Microsoft face-to-face with
..NET developers before .NET was initially released.

> which will show you that it does, in fact, protect us from memory leaks

Did you interpret any of my comments to imply that GC does not eliminate
memory leaks?

> which makes much of what you have been inquiring about (where to use
> Try...Catch and creating "bullet-proof" non-crashable code), not an issue
> in all but extreme coding scenarios or poorly designed hardware
> architectures.

I'm sorry, but I'm just blown away by some of the things you are saying. The
fact is that I wish I had a dollar for every Website I've played around with
that threw up the familiar ASP.NET error page. If you are happy with that,
then it is not an issue. Otherwise, it should be an issue.

> As for your original concern about persisting a copy of the data in a
> DataSet, again I'll refer you to more research on the GC, the DataSet and
> DataTable classes, and the overhead of keeping an active database "hook"
> longer than is really needed.

That issue has already been resolved to my satisfaction. The issue is a bit
more complex about when to use a DataReader and when to use a DataSet, but
the issue about closing the connection made perfect sense to me, I
understood it, and I moved on.

--
Jonathan Wood
SoftCircuits Programming
http://www.softci...

Scott M.

12/7/2007 4:23:00 AM

0


"Jonathan Wood" <jwood@softcircuits.com> wrote in message
news:ui7h$38NIHA.4272@TK2MSFTNGP06.phx.gbl...
> Scott,
>
>> GC does more than optimize the heap, it "manages" the heap and makes
>> decisions about "when" and "if" objects need to be destroyed.
>
> That process of destroying objects as well as rearranging memory is what I
> meant by optimize.
>
>> To say that the GC can't prevent us from running out of memory is
>> incorrect. It most certainly can and does.
>
> It may be that the chances you'll run out of memory are exceedingly low,
> but to suggest GC prevents us from doing so makes no sense. If you still
> disagree, have a look at what MS says about the new operator allocating
> memory in C#:
>
> "If the new operator fails to allocate memory, it throws the exception
> OutOfMemoryException."
> http://msdn2.microsoft.com/en-us/librar...(VS.71).aspx
>
> Obviously, there is only so much memory. How can GC prevent us from
> running out?

I've said that it is *possible* for applications to run out of memory, but
you've snipped those comments in your replies. I've said that the causes for
running out of memory are going to be poor hardware architecture, unmanaged
resource allocation (which is outside of the GC's control) and/or poor
programming. No one can ever make you a rock-solid guarantee that these
things won't happen, but if we just talk about what the GC has control over
(managed code) and we talk about that managed code written by someone with a
basic understanding of object memory allocation, we do find that the GC
protects us from running out of memory by cleaning the heap when memory
resources begin to get low. If your response to that statement is along the
lines of "What if there are not enough resources for the GC to release and
so we still run out of memory?", then my response is that we are working in
a poorly architected hardware environment and this is not a programming
issue at all.

>
>> scenario you've shown, it is unneccessary. I do not believe that having a
>> basic understanding of the nuances of a class so that I can use them more
>> effectively breaks encapsulation.
>
> Then we apparently have different working definitons of "encapsulation."

I guess we do.

>
>> Ah, but I've been doing this long enough (from this side of the fence) to
>> understand the benefits of OOP in a managed environment.
>
> The principles and benefits of OOP have not changed just because OOP has
> been implemented in a managed environment.
>
>> What if I had just told you to call dispose on any object that has such a
>> method and that this would be sufficient to cause the object to clean up
>> appropriately? That would put your whole argument about encapsulation to
>> rest, wouldn't it? Because if you choose to code by that rule, it will
>> not cause you *any* troubles in any situation you encounter, ever.
>
> It could affect performance

Not calling it could affect performance. It's there because in most cases
it performs important work that prevents problems from occuring.

> and, no matter how easy the IDE makes it to determine whether or not a
> class implements Dispose, it still must be known and so it supports my
> position.

Let me ask you something...How did you find out that a Command object has an
ExecuteReader method? Didn't you have to somehow "know" that there was a
method that wouuld invoke your command's commandText and return an object
that you could use to iterate over the results of that commandText? I just
don't understand your assertion that to investigate the members of a class
to determine what the available members are and get a basic understanding of
what those members do is counter to any OOP principle. I'll say it again,
encapsulation does not mean we shouldn't have to look at an object's
interface and try to determine what the variouse interface members do, it
means that we shouldn't have to know or care *how* those members do what
they do. Without becomming knowledgeable about the existence of the
members, you couldn't write a line of code.

>
>> I really think that you should do a little more research on the GC
>
> Perhaps you can point out one aspect of GC that I have demonstrated I do
> not understand.

How about two?

1. You said that the GC cannot protect us from running out of memory, which
is incorrect. I have explained that what I mean by this is not that the GC
will protect us from *all* out of memory exceptions (poor hardware design,
poor coding techniques, unmanged resource allocation outside of the GC's
control), but for what the GC does have control over, it can and does
prevent us from running out of memory. Even though I've said this a few
times now, you still seem to disagree with this, which is just incorrect.

2. You also questioned me when I said that the GC determines *if* objects
will be released, indicating that you believed that all objects will be
removed at some point, which may not be the case. In fact, and you may
already know this, the GC doesn't finalize all "collectable" objects when it
is cleaning the heap. Objejcts are organized into "generations" and
promoted upon each collect until they eventually reach a point where they
will be collected in the next collection cycle - - but, as I've indicated,
in a system that has a lot of available resources, there may not be a need
for the GC to collect, resulting in objects that are elligible for
collection, but not collected.

>I have discussed these issues at Microsoft face-to-face with .NET
>developers before .NET was initially released.

I don't see how that makes your inaccurate statements about the GC, the
memory implications of using DataReaders and DataSets, and the potential for
creating instances causing us to run out of memory any less incorrect.

>
>> which will show you that it does, in fact, protect us from memory leaks
>
> Did you interpret any of my comments to imply that GC does not eliminate
> memory leaks?

No, I simply added this as an additional benefit of what the GC does - - I
believe there was more to my statement above, but you snipped it.

>
>> which makes much of what you have been inquiring about (where to use
>> Try...Catch and creating "bullet-proof" non-crashable code), not an issue
>> in all but extreme coding scenarios or poorly designed hardware
>> architectures.
>
> I'm sorry, but I'm just blown away by some of the things you are saying.
> The fact is that I wish I had a dollar for every Website I've played
> around with that threw up the familiar ASP.NET error page. If you are
> happy with that, then it is not an issue. Otherwise, it should be an
> issue.

I don't know what statements I've made that you are blown away by, but your
statement above is too general for me to give a specific reply to. I will
say that, you've admitted that you are new to much of this .NET stuff and
I've told you that I've worked with and taught it for nearly 7 years now.
You've also heard from "Cowboy" a.k.a. Greg (who has written a book on ADO
..NET) on this. Perhaps there's something we know on these issues that you
don't?

You'll also have to be more specfic as to what error page you are referring
to. Because, as I've said, you can write poor code in any language and if
you are seeing ASP .NET error pages on production web sites, then the
developer's of those sites didn't even know how to disable exception error
messages from displaying to the general public in web.config, which tells me
that you are using examples of sites that use bad code or are written by
poorly skilled developers to start with. I mean give me a language and I
can crash the system it runs on pretty easily with a simple loop.

>
>> As for your original concern about persisting a copy of the data in a
>> DataSet, again I'll refer you to more research on the GC, the DataSet and
>> DataTable classes, and the overhead of keeping an active database "hook"
>> longer than is really needed.
>
> That issue has already been resolved to my satisfaction. The issue is a
> bit more complex about when to use a DataReader and when to use a DataSet,
> but the issue about closing the connection made perfect sense to me, I
> understood it, and I moved on.

Well, by your comment here, it makes me wonder how much you really do
understand all of this, because when to use a DataReader vs. when to use a
DataSet is actually not that complex of a decision. Understanding the GC's
role and how well it fufills that role is key to understanding why this.

Anyway, I do wish you good luck in your .NET endeavors.

-Scott

>
> --
> Jonathan Wood
> SoftCircuits Programming
> http://www.softci...
>