Discussion:
ADOX - Access table creation with nullable columns in C#
(too old to reply)
giovanni
2009-02-18 15:46:01 UTC
Permalink
i've just created an Access Database using ADOX library, but i need to set
some column to accept null value....

some lime of my code is...

.....
Table nTable = new Table();
nTable.Name = "tblName";
nTable.Columns.Append("name", DataTypeEnum.adVarWChar, 255);
....
.....

how to set the column "name" to accept null value??
Ralph
2009-02-18 17:21:09 UTC
Permalink
Post by giovanni
i've just created an Access Database using ADOX library, but i need to set
some column to accept null value....
some lime of my code is...
.....
Table nTable = new Table();
nTable.Name = "tblName";
nTable.Columns.Append("name", DataTypeEnum.adVarWChar, 255);
....
.....
how to set the column "name" to accept null value??
Not all attributes or properties of a Field are applicable for all Fields.
Thus some attributes are not available until the Field is created. Make two
passes - one creating the 'raw' Fields, another to set specific attributes.

-ralph
Ralph
2009-03-04 03:18:18 UTC
Permalink
Post by Ralph
Post by giovanni
.....
Table nTable = new Table();
nTable.Name = "tblName";
nTable.Columns.Append("name", DataTypeEnum.adVarWChar, 255);
....
.....
how to set the column "name" to accept null value??
Not all attributes or properties of a Field are applicable for all Fields.
Thus some attributes are not available until the Field is created. Make two
passes - one creating the 'raw' Fields, another to set specific attributes.
Upon further thought - "make two passes" isn't very useful ... here is a VB6
way to do it. (You can easily translate to C#.)

Dim cat As New ADOX.Catalog
Dim nTable As ADOX.Table
Set cat.ActiveConnection = <your_connection>
Set nTable = New ADOX.Table
nTable.Name = "tblName"

'Append the columns.
With tbl.Columns
.Append "name", adVarWChar, 25
... ' Append all the Fields
...
' Now go back and set the field properties.
With !name
Set .ParentCatalog = cat
.Properties("Nullable") = True
.Properties("Jet OLEDB:Allow Zero Length") = True
End With
... ' set other fields
End With

Hope this is more useful
-ralph
Brian Jahelka
2009-03-06 04:48:12 UTC
Permalink
I've seen this example in VB6 all over the web. I can't make it work in .net.

I'm programming in vb.net (2.0) against the ADO 6.0 and ADOX 6.0 that is on
my Vista box. I am trying to update/change the schema on an Access 2000
database.

Here is most of my code:

' add table
---------------------------------------------------------------------------
Dim tbl As New ADOX.Table
tbl.ParentCatalog = Cat
tbl.Name = RefTable.TableName & "New"

Trace.WriteLine(" === Created New Table in ADOX: " & tbl.Name &
" ===")

' add columns
---------------------------------------------------------------------------

' first get them sorted by ordinal (ADOX returns them
alphabetically)
Dim cols As New SortedList(Of Integer, String)
For Each cname As String In RefTable.Columns.Keys
cols.Add(RefTable.Columns(cname).Ordinal, cname)
Next

' now cols is sorted on the key (ordinal), so for each through
this SortedList collection
For Each cname As String In cols.Values
' add column
---------------------------------------------------------------------------
Dim col As ADOX.Column
col = New ADOX.Column
col.ParentCatalog = Cat
col.Name = cname

With RefTable.Columns(cname)
Trace.WriteLine(" Created New Column in ADOX: " &
col.Name & " ===")
col.Type = .Type
col.DefinedSize = .DefinedSize
col.Attributes = .Attributes
tbl.Columns.Append(col)
Trace.WriteLine(" Appended New Column in ADOX: "
& col.Name & " ===")

col.ParentCatalog = Cat
Trace.WriteLine(" Trying to update Properties in
ADOX: " & cname & " ===")
tbl.Columns(cname).Properties("Description").Value =
.Description
' cannot set nullable if it is a boolean field
If Not isADOXBoolean(.Type) Then
tbl.Columns(cname).Properties("Default").Value =
.DefaultValue
tbl.Columns(cname).Properties("Nullable").Value =
.Nullable
End If
Trace.WriteLine(" Updated Properties in ADOX: " &
cname & " ===")
End With
Next
Cat.Tables.Append(tbl)
Trace.WriteLine(" === Appened New Table: " & tbl.Name & " ===")


Running this gets me the following (very ambiguous) error:

System.Runtime.InteropServices.COMException (0x80040E21):

ADO Error: -2147217887
ADO Description: Multiple-step OLE DB operation generated errors. Check each
OLE DB status value, if available. No work was done.
ADO Source: Microsoft JET Database Engine

This error fails on the last line where I actually append the table to the
catalog.

I have been trying to get this to work for the last THREE days (and nights)
solid and I cannot figure out what I'm doing wrong. My Google search history
is very long right now. =)

ANY help or comments or nudges in the right direction would be so much
appreciated. TIA!
Post by Ralph
Post by Ralph
Post by giovanni
.....
Table nTable = new Table();
nTable.Name = "tblName";
nTable.Columns.Append("name", DataTypeEnum.adVarWChar, 255);
....
.....
how to set the column "name" to accept null value??
Not all attributes or properties of a Field are applicable for all Fields.
Thus some attributes are not available until the Field is created. Make
two
Post by Ralph
passes - one creating the 'raw' Fields, another to set specific
attributes.
Upon further thought - "make two passes" isn't very useful ... here is a VB6
way to do it. (You can easily translate to C#.)
Dim cat As New ADOX.Catalog
Dim nTable As ADOX.Table
Set cat.ActiveConnection = <your_connection>
Set nTable = New ADOX.Table
nTable.Name = "tblName"
'Append the columns.
With tbl.Columns
.Append "name", adVarWChar, 25
... ' Append all the Fields
...
' Now go back and set the field properties.
With !name
Set .ParentCatalog = cat
.Properties("Nullable") = True
.Properties("Jet OLEDB:Allow Zero Length") = True
End With
... ' set other fields
End With
Hope this is more useful
-ralph
Ralph
2009-03-06 08:22:50 UTC
Permalink
Post by Brian Jahelka
I've seen this example in VB6 all over the web. I can't make it work in .net.
Essentially you have one too many 'news'.
Post by Brian Jahelka
' add table
--------------------------------------------------------------------------
-
Post by Brian Jahelka
Dim tbl As New ADOX.Table
tbl.ParentCatalog = Cat
tbl.Name = RefTable.TableName & "New"
Trace.WriteLine(" === Created New Table in ADOX: " & tbl.Name &
" ===")
' add columns
--------------------------------------------------------------------------
-
Post by Brian Jahelka
' first get them sorted by ordinal (ADOX returns them
alphabetically)
Dim cols As New SortedList(Of Integer, String)
For Each cname As String In RefTable.Columns.Keys
cols.Add(RefTable.Columns(cname).Ordinal, cname)
Next
' now cols is sorted on the key (ordinal), so for each through
this SortedList collection
For Each cname As String In cols.Values
' add column
--------------------------------------------------------------------------
-
Post by Brian Jahelka
Dim col As ADOX.Column
col = New ADOX.Column
Here is where I think it goes wrong.
The documentation says you can either supply the column object, or provide
the name, DataType, and Size.
Post by Brian Jahelka
tbl.Columns.Append(col)
It has been my experience that supplying the column object only works for a
few basic types. It appears that allowing the .Append method to contruct the
object always works.

[My guess is the object created within .Append method is better prepared in
some fashion - subclassed? I really don't know.]

Subsquent attempts to set additional properties should be done on the column
object retreived from the 'appended collection'.
Post by Brian Jahelka
ADO Error: -2147217887
ADO Description: Multiple-step OLE DB operation generated errors. Check each
OLE DB status value, if available. No work was done.
ADO Source: Microsoft JET Database Engine
That is the error I usually get when I attempt to pass a full column object.

hth
-ralph
Brian Jahelka
2009-03-06 15:01:02 UTC
Permalink
Post by Ralph
It has been my experience that supplying the column object only works for a
few basic types. It appears that allowing the .Append method to contruct the
object always works.
[My guess is the object created within .Append method is better prepared in
some fashion - subclassed? I really don't know.]
Subsquent attempts to set additional properties should be done on the column
object retreived from the 'appended collection'.
Post by Brian Jahelka
ADO Error: -2147217887
ADO Description: Multiple-step OLE DB operation generated errors. Check
each
Post by Brian Jahelka
OLE DB status value, if available. No work was done.
ADO Source: Microsoft JET Database Engine
That is the error I usually get when I attempt to pass a full column object.
hth
-ralph
I tried this and it doesn't seem to make any difference...

One nagging question I have is about the Properties("Nullable") value
(boolean) vs. the Attributes value (ColumnAttributesEnum). It appears that
they contradict one another. According to the docs, valid values for
Attributes are 0 (not specified), or 1 (adColFixed), and 2 (adColNullable).
Then of course you have Properties("Nullable") which can be true or false.
It would seem to me that if you set Attributes to 2 (adColNullable) and then
set Properties("Nullable") to false, those would be contradictary.

To add to the confusion, I have been using ADOX to get the existing
properties of columns in my database, and sometimes I get an Attributes = 3
!?!?! How in the world is that possible? AFAIK, 3 is not a vaild value for
Attributes based on the ColumnAttributesEnum.

To step back and take a look at things overall... I have an app I am
writing in vb.net that uses an Access 2000 database for a backend. It is a
very data intensive application. As I add features to my app, I am adding
tables and/or columns to the database to handle the new features. I also
have been playing with the indexes in the database while tuning it for speed.
This is all fine and dandy if I was the only one using my app then no
biggie. But I have many clients using it with live data in their own
database. I just want to be able to update the schema automatically with
every new release of my application. It is very difficult to have the client
send me their live database, just so I can go in and make schema changes for
them and then return it to them. Of course, when doing this by hand, I end
up with databases in the client's hands that probably don't have ALL of the
schema changes it should, and I've already had situations where I forgot to
change something and then bad things happen. So I'm just trying to automate
the process, and I thought serializing the database structure to XML and
distributing with my app, and then on start up checking the schema vs their
live database would be a good way to go. This has just been one giant
headache.

I'm starting to think that I should just distribute a master database that
has no records, but a good schema, and just copy all of the data out of their
live database and into the new master. This seemed like a horribly
inefficient way to do things from the get go, but after fighting ADOX for so
long, it is starting to sound like a good idea.

My problem seems like this would be a VERY common problem that almost all
developers would face. Why isn't there a more standard way to do this? I
search the web and I read TONS of books, and no one really seems to want to
talk about this subject.
Ralph
2009-03-06 17:51:01 UTC
Permalink
Post by Brian Jahelka
Post by Ralph
It has been my experience that supplying the column object only works for a
few basic types. It appears that allowing the .Append method to contruct the
object always works.
[My guess is the object created within .Append method is better prepared in
some fashion - subclassed? I really don't know.]
Subsquent attempts to set additional properties should be done on the column
object retreived from the 'appended collection'.
Post by Brian Jahelka
ADO Error: -2147217887
ADO Description: Multiple-step OLE DB operation generated errors. Check
each
Post by Brian Jahelka
OLE DB status value, if available. No work was done.
ADO Source: Microsoft JET Database Engine
That is the error I usually get when I attempt to pass a full column object.
hth
-ralph
I tried this and it doesn't seem to make any difference...
I'm surprised. I threw together a quick little C# test and it worked.
However, I didn't duplicate your code or build a major project - I just
opened a database, created a table, set some properties, and closed.

Any further testing of your code will have to wait until the weekend.
Hopefully someone else can see something in the meantime.

I can only offer the poor suggestion that you burn everything down to the
water-line (if not sink the ship) and start over with a new database file
and a simple routine with hard-coded values (ie, forget mining an array for
the moment). Once that works go back to providing "values" with your custome
source.
Post by Brian Jahelka
One nagging question I have is about the Properties("Nullable") value
(boolean) vs. the Attributes value (ColumnAttributesEnum). It appears that
they contradict one another. According to the docs, valid values for
Attributes are 0 (not specified), or 1 (adColFixed), and 2
(adColNullable).
Post by Brian Jahelka
Then of course you have Properties("Nullable") which can be true or false.
It would seem to me that if you set Attributes to 2 (adColNullable) and then
set Properties("Nullable") to false, those would be contradictary.
To add to the confusion, I have been using ADOX to get the existing
properties of columns in my database, and sometimes I get an Attributes = 3
!?!?! How in the world is that possible? AFAIK, 3 is not a vaild value for
Attributes based on the ColumnAttributesEnum.
The ADOX "Attributes Property" is a combination of ColumnAttributeEnum
values -
thus "3" is
adColFixed || adColNullable := 1 + 3 == 3
a column that is Fixed and Nullable

-ralph
Ralph
2009-03-06 18:57:36 UTC
Permalink
">
Post by Ralph
The ADOX "Attributes Property" is a combination of ColumnAttributeEnum
values -
thus "3" is
adColFixed || adColNullable := 1 + 3 == 3
a column that is Fixed and Nullable
Ooops!

Make that ...
adColFixed || adColNullable := 1 + 2 == 3

-ralph
Brian Jahelka
2009-03-06 19:24:02 UTC
Permalink
Post by Ralph
">
Post by Ralph
The ADOX "Attributes Property" is a combination of ColumnAttributeEnum
values -
thus "3" is
adColFixed || adColNullable := 1 + 3 == 3
a column that is Fixed and Nullable
Ooops!
Make that ...
adColFixed || adColNullable := 1 + 2 == 3
-ralph
And the light bulb goes ON!!! Woohoo! It still works!

So what about the attributes vs. properties("Nullable") thing? Couldn't
they still be competing against one another? I'm wondering if somehow my
existing database has competing values that ADOX won't let you set. This
might explain why I am having issues.

I think your advice to break it down to the most basic of basics and make
sure I can get this to work in a testing scenario (which I already thought I
was in LOL!) is a good one. I'm going to take some of the existing code I
have and get back to the basics and add single columns at a time with
different settings to see what happens.

Thanks for all of your help Ralph.
Jahelka
2009-03-07 03:26:54 UTC
Permalink
Post by Ralph
">
Post by Ralph
The ADOX "Attributes Property" is a combination of ColumnAttributeEnum
values -
 thus "3" is
    adColFixed || adColNullable := 1 + 3 == 3
a column that is Fixed and Nullable
Ooops!
Make that ...
      adColFixed || adColNullable := 1 + 2 == 3
-ralph
Apparently the reply to this one that I posted earlier today didn't
make it (I was posting from the microsoft site, it appears to be
"Temporarily out of Service" right now. Posting from Google Groups...

Light bulb goes ON! (Good to know it still works)

1 + 2 = 3 makes a lot of sense now.

I was also saying that I think your advice to abandon ship and get
back to the basics was a very good one. I ~thought~ I was in the
testing stages as I have been writing in a test app, but in reality,
it was becoming it's own beast. I just started over basically from
scratch. I'm too hard headed to go to hand hard coding for testing.
I've got a list box that shows tables, a datagrid that shows column
properties, and a detail form on the side that will soon (hopefully)
allow you to edit each property individually. Once I play with that a
bit using my existing database, I'm sure I will figure out real quick
which property changes cause problems. Then I think I'll add in an
"Add Column" button and figure out what all happens when adding a new
column with various properties defined in different ways.

I think the main problem with my trial run is that I was trying to
just update everything, whether it changed or not. Of course, that is
because I thought this would be easy. =) Hopefully I am very close
to figuring out what doesn't work and why...
Jahelka
2009-03-07 06:44:05 UTC
Permalink
Post by Jahelka
I think the main problem with my trial run is that I was trying to
just update everything, whether it changed or not.  Of course, that is
because I thought this would be easy.  =)  Hopefully I am very close
to figuring out what doesn't work and why...
Some initial findings:

So far I have just been trying to UPDATE and APPEND columns in an
existing table that has data.

Here is my code with findings commented for UPDATING an existing
column:

Dim conADO As New ADODB.Connection
Dim Cat As New ADOX.Catalog
conADO.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
My.Settings.TargetMDB & ";Jet OLEDB:Engine Type=5;")
Cat.ActiveConnection = conADO

Dim col As ADOX.Column
col = Cat.Tables(gTblName).Columns(gColName)

' cannot CHANGE!
If txbDefinedSize.Tag = "Changed" Then
If IsNumeric(txbDefinedSize.Text) Then
col.DefinedSize = CInt(txbDefinedSize.Text)
Else
col.DefinedSize = 0
End If
End If

' cannot CHANGE!
If txbAttributes.Tag = "Changed" Then
col.Attributes = CInt(txbAttributes.Text)
End If

If txbDefaultValue.Tag = "Changed" Then
col.Properties("Default").Value = txbDefaultValue.Text
End If

If txbDescription.Tag = "Changed" Then
col.Properties("Description").Value = txbDescription.Text
End If

' cannot CHANGE!
If ckbNullable.Tag = "Changed" Then
col.Properties("Nullable").Value = ckbNullable.Checked
End If

If ckbAllowZeroLength.Tag = "Changed" Then
col.Properties("Jet OLEDB:Allow Zero Length").Value =
ckbAllowZeroLength.Checked
End If

' cannot CHANGE!
If ckbCompressed.Tag = "Changed" Then
col.Properties("Jet OLEDB:Compressed UNICODE
Strings").Value = ckbCompressed.Checked
End If

Cat = Nothing
conADO.Close()
conADO = Nothing


Here is my code for APPENDING a column to an existing table WITH data:

Dim conADO As New ADODB.Connection
Dim Cat As New ADOX.Catalog
conADO.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
My.Settings.TargetMDB & ";Jet OLEDB:Engine Type=5;")
Cat.ActiveConnection = conADO

Dim tbl As New ADOX.Table
Dim col As New ADOX.Column
tbl = Cat.Tables(gTblName)

If txbDefinedSize.Text.Length = 0 Then
tbl.Columns.Append(txbName.Text, cbxType.SelectedValue)
Else
tbl.Columns.Append(txbName.Text, cbxType.SelectedValue,
CInt(txbDefinedSize.Text))
End If
col = tbl.Columns(txbName.Text)
'col.ParentCatalog = Cat ' ERROR: Operation is not allowed in
this context. (makes sense to me, the table already exists in this
case)

' cannot CHANGE!
If txbAttributes.Tag = "Changed" Then
col.Attributes = CInt(txbAttributes.Text)
End If

If txbDefaultValue.Tag = "Changed" Then
col.Properties("Default").Value = txbDefaultValue.Text
End If

If txbDescription.Tag = "Changed" Then
col.Properties("Description").Value = txbDescription.Text
End If

' cannot CHANGE!
If ckbNullable.Tag = "Changed" Then
col.Properties("Nullable").Value = ckbNullable.Checked
End If

If ckbAllowZeroLength.Tag = "Changed" Then
col.Properties("Jet OLEDB:Allow Zero Length").Value =
ckbAllowZeroLength.Checked
End If

' cannot CHANGE!
If ckbCompressed.Tag = "Changed" Then
col.Properties("Jet OLEDB:Compressed UNICODE
Strings").Value = ckbCompressed.Checked
End If

Cat = Nothing
conADO.Close()
conADO = Nothing

As you (and more importantly, ME) can see, there are a lot of things
you can't do with ADOX (at least with an existing schema and data)!
The more I think about it the more I suppose that it makes sense that
this is a much more complicated thing to do than I give it credit
for. Although I have seen MS program some very complicated stuff,
what I'm trying to do still seems pale in comparison. =)

Next I'll move on to adding a completely new table and see what ADOX
can and can't do when I do that. It is looking to me like my only
solution is going to have to include using DDL AND ADOX. Shesh, just
what I really wanted to do, have to use two completely different
technologies to accomplish one task. LOL!
Jahelka
2009-03-07 08:52:20 UTC
Permalink
Well, after further review, still can't seem to change EITHER the
attribute property or the nullable property. Even on a table with no
rows. Getting the same error as before. With the code listed above.

DDL allows me to append a column, and by default both nullable AND
allow zero length are true. I can then using ADOX change allow zero
length to false. I can also then use DDL to alter the column using
the keywords "NOT NULL" and change it so that nullable is now FALSE
(and the column attribute property updates to = 0, when it was 2 to
start with). But, I cannot change it back (using either ADOX or
DDL). So it would appear to me so far, that once a column has been
deemed not nullable, you can't recover from that without recreating
the table.

I have a full example project if anyone (Ralph) wants to look at it.
Or I can post more code, but what I have already posted now is what
I'm using. Maybe I am just confirming what everyone else already
knows. But the original intent of this post by giovanni still stands
as far as I'm concerned. I still can't make a column nullable or not
nullable, either through the attributes property or thru the properties
("Nullable") property using ADOX.
Bob Barrows
2009-03-07 11:40:42 UTC
Permalink
Yeah, ADOX was kind of an "afterthought" for the MS developers, when they
encountered a backlash from developers using Jet backends who discovered
that the early versions of ADO provided no way to do the database schema
manipulation they were used to doing with DAO. So, ADOX was quickly whipped
together and tacked on, along with an announcement that since they were
planning to deprecate Jet, ADOX would not likely receive further
development.

As you have discovered, the nullability is easily maintained using DDL. If
that does not suit your needs, then I would suggest using the more robust
DAO library, to which Ralph alluded. DAO was very mature when MS made the
switch to ADO, and remains to this day, the best technology to use with Jet.
Michael Kaplan wrote an article a long time ago discussing the various tasks
that could be performed with DAO that were not and would likely never be
possible with ADO/ADOX. If you do a search at Trigeminal.com, you should be
able to find it.
Post by Jahelka
Well, after further review, still can't seem to change EITHER the
attribute property or the nullable property. Even on a table with no
rows. Getting the same error as before. With the code listed above.
DDL allows me to append a column, and by default both nullable AND
allow zero length are true. I can then using ADOX change allow zero
length to false. I can also then use DDL to alter the column using
the keywords "NOT NULL" and change it so that nullable is now FALSE
(and the column attribute property updates to = 0, when it was 2 to
start with). But, I cannot change it back (using either ADOX or
DDL). So it would appear to me so far, that once a column has been
deemed not nullable, you can't recover from that without recreating
the table.
That almost makes sense. A field set to nullable might contain nulls when
you try to toggle it to not nullable. I would not be surprised if that was
not what occurred behind the scenes when you used Access to change the
Required property of a field in Design mode.

With SQL Server, a columns nullability can be altered via DDL, an error
being raised only when the column contains nulls when you are trying to set
it to "NOT NULL".

I'm going to quickly see what can be done via DAO.
--
Microsoft MVP - ASP/ASP.NET - 2004-2007
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Bob Barrows
2009-03-07 11:48:43 UTC
Permalink
Post by Bob Barrows
I'm going to quickly see what can be done via DAO.
Hmm, DAO makes it pretty simple:
Dim db As Database, tdf As TableDef
Set db = CurrentDb
Set tdf = db.TableDefs("cities")
tdf.Fields("price").Required = True

works just fine. It would be advisable to set the DefaultValue property
before setting a nullable field to Required ..
--
Microsoft MVP - ASP/ASP.NET - 2004-2007
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Ralph
2009-03-07 18:31:32 UTC
Permalink
Post by Bob Barrows
Yeah, ADOX was kind of an "afterthought" for the MS developers, when they
encountered a backlash from developers using Jet backends who discovered
that the early versions of ADO provided no way to do the database schema
manipulation they were used to doing with DAO. So, ADOX was quickly whipped
together and tacked on, along with an announcement that since they were
planning to deprecate Jet, ADOX would not likely receive further
development.
As you have discovered, the nullability is easily maintained using DDL. If
that does not suit your needs, then I would suggest using the more robust
DAO library, to which Ralph alluded. DAO was very mature when MS made the
switch to ADO, and remains to this day, the best technology to use with Jet.
Michael Kaplan wrote an article a long time ago discussing the various tasks
that could be performed with DAO that were not and would likely never be
possible with ADO/ADOX. If you do a search at Trigeminal.com, you should be
able to find it.
Ha.

Good for you Bob.

After years of consulting and getting almost booed out of meetings, without
knowing more about my audience, I've become too shy at suggesting DAO. It is
hard enough to suggest it to a VB crowd, let alone to anyone enamored with
dotNet. But the fact remains it is the single most proficient method to
access and manage Jet databases. And more people, who have to work with Jet,
would be happier and have more time to spend with family and friends if they
understood that.

{It is interesting to note that the new ACE for ACEDB is little more than an
"advanced" version of DAO.}

It is a topic beyond this newsgroup (and I haven't played much with it
myself), but it is possible to use DAO from dotNet. Just include a reference
to DAO360.DLL or perhaps through "Microsoft.Office.Interop.Access.Dao". For
additional information you should post to a dotNet data newsgroup. However
one warning - be ready to ignore the derisive scoffing you will get from all
the 'experts'. lol

-ralph
Bob Barrows
2009-03-07 19:16:28 UTC
Permalink
Post by Ralph
After years of consulting and getting almost booed out of meetings,
without knowing more about my audience, I've become too shy at
suggesting DAO. It is hard enough to suggest it to a VB crowd, let
alone to anyone enamored with dotNet.
... which is very strange since that is the crowd that should be using DAO.
If you're doing a server-based, multi-threaded app (such as ASP.ASP.Net),
then DAO is definitely not the tool to use. For desktop apps, it's got it
all over ADO/OLE DB.
--
Microsoft MVP - ASP/ASP.NET - 2004-2007
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"
Ralph
2009-03-07 19:58:47 UTC
Permalink
Post by Bob Barrows
Post by Ralph
After years of consulting and getting almost booed out of meetings,
without knowing more about my audience, I've become too shy at
suggesting DAO. It is hard enough to suggest it to a VB crowd, let
alone to anyone enamored with dotNet.
... which is very strange since that is the crowd that should be using DAO.
If you're doing a server-based, multi-threaded app (such as ASP.ASP.Net),
then DAO is definitely not the tool to use. For desktop apps, it's got it
all over ADO/OLE DB.
lol

Spend a bit of time slumming in .vb.general.discussion and you will find it
not 'strange' at all.

The typical thread runs something like this:
"I've got this problem with Access ..."
You shouldn't be using DAO as it has been depricated by MS, you should use
the newer ADO since it scales better for a remote database.
Well, actually you shouldn't be using a file-based database either. You
should be using a 'real' RDBMS like SQL Server.
<someone may also throw in a suggestion to use Automation at this point. At
which time someone else will point out that you have to have MSAccess
installed....>
Eventually everyone agrees that ADO with SQL Server is the way to go for a
full-service enterprise distributed application that is flexible for the
"future".
The fact the OP asked a question concerning Jet with a Desktop application
is quickly lost because the OP shouldn't be doing that in the first place.
<g>

-ralph
Jahelka
2009-03-07 20:57:28 UTC
Permalink
Hey guys, it is great to hear you talk about this stuff.

I earlier scoffed at using VB6, mainly because I have invested huge
amounts of time over the last 4-5 years in .net, and now that I
know .net fairly well, going back to VB6 just seems cumbersome to me.

I don't necessarily mind using DAO, but the drum beat (as you guys
have noted), is that you shouldn't be using that "old" technology. I
can happily add in a reference to DAO 3.6 and code away. But when
everything you read or see says using that "old" technology is a bad
idea, I was kind of shy about going that route. You sometimes think
that the "new technology" will make your life easier, which I suppose
is the case most of the time. I am finding out the hard way on this
one that the "new" technology is crap. =)

I just pulled my old Access 97 Developer's Handbook off the shelf.
Man that brings back some memories... I think I'm going to change up
my code a bit and see how the DAO stuff works out.

When I first picked up VS2005 and started coding against my Access
database, I was all excited about this new stuff with automatic data
binding and all the neat stuff that was to go along with. One thing
that had me completely incredulous, was the inability for the user to
pick what database they wanted to connect to at run time. This was
HARD CODED into the application settings and could not be changed at
run-time. WTF!? I had to do that first work around where I manually
edited the app.settings.xml file to change the database connection,
then FORCE the user to restart the app. I just flat out could not
believe that doing something so simple had been made so difficult
with .net. And to this day, each time I have to connect to a
different database (which is all the time), it pisses me off that I
can't just change it on the fly without an app restart.

My application runs in a distributed environment, with no central
servers or anything like that. A file based database is really the
only solution. I don't even want to think about having to get a user
to install SQL Express on their machine. But that would create whole
new problems, like how do I get my customers data on the web. Right
now they just upload the .mdb and done. With anything else it would
certainly be much more difficult...

I'm self employed and don't have anyone to go off on, so sometimes I
let it come out on the internet. I'll stop ranting now... =)

Ralph
2009-03-06 18:54:35 UTC
Permalink
"Brian Jahelka" <***@discussions.microsoft.com> wrote in message news:28D36C88-4F7C-4C8F-AB0B-***@microsoft.com...
I felt that this is a different topic and so needs a separate response.

<snipped>
Post by Brian Jahelka
To step back and take a look at things overall... I have an app I am
writing in vb.net that uses an Access 2000 database for a backend. It is a
very data intensive application. As I add features to my app, I am adding
tables and/or columns to the database to handle the new features. I also
have been playing with the indexes in the database while tuning it for speed.
This is all fine and dandy if I was the only one using my app then no
biggie. But I have many clients using it with live data in their own
database. I just want to be able to update the schema automatically with
every new release of my application. It is very difficult to have the client
send me their live database, just so I can go in and make schema changes for
them and then return it to them. Of course, when doing this by hand, I end
up with databases in the client's hands that probably don't have ALL of the
schema changes it should, and I've already had situations where I forgot to
change something and then bad things happen. So I'm just trying to automate
the process, and I thought serializing the database structure to XML and
distributing with my app, and then on start up checking the schema vs their
live database would be a good way to go. This has just been one giant
headache.
I'm starting to think that I should just distribute a master database that
has no records, but a good schema, and just copy all of the data out of their
live database and into the new master. This seemed like a horribly
inefficient way to do things from the get go, but after fighting ADOX for so
long, it is starting to sound like a good idea.
Well here is an unsatisfactory suggestion: (lol)

Using ADOX isn't that difficult. Using ADOX in VB6 is a trivial process with
plenty of working examples on the web. At the moment I don't see any reason
why you shouldn't be able to manage it using C#, but if you are, and have an
immediate need ... you might consider using VB6 or even VBA/VBS to create a
separate utility to manage database changes. After all - it only needs to
run once and likely outside the main application. Once you have something
that works for your domain - translating to a dotNet solution shouldn't be
that difficult.

[I found that using DAO to be even easier to use to manage DDL in Jet
databases. I know - Arrrggggghhh! lol]

Not the best of solutions, but having a working utility (no matter how ugly)
might bring to light what the real issues are.
Post by Brian Jahelka
My problem seems like this would be a VERY common problem that almost all
developers would face. Why isn't there a more standard way to do this? I
search the web and I read TONS of books, and no one really seems to want to
talk about this subject.
The reason for the apparent "silence" on this subject is simply because
there IS no "standard way" to do it. Consider for a moment that there is no
"standard way" to store data or manipulate data in an application. Any
solution would be very specific for your domain and awkward if applied to
another. Just as other's solutions would be awkward if ported to yours.

The key of course is to have a database design that is amendable to
"changes". And then an Application Object model that is equally amendable to
"changes" - then any adjustments that need to be made can always be managed
by employing that first maxim of programming - "There is no problem that
can't be resolved with another layer of redirection". lol

-ralph
Brian Jahelka
2009-03-06 19:32:05 UTC
Permalink
Post by Ralph
Post by Brian Jahelka
I'm starting to think that I should just distribute a master database that
has no records, but a good schema, and just copy all of the data out of
their
Post by Brian Jahelka
live database and into the new master. This seemed like a horribly
inefficient way to do things from the get go, but after fighting ADOX for
so
Post by Brian Jahelka
long, it is starting to sound like a good idea.
Well here is an unsatisfactory suggestion: (lol)
Using ADOX isn't that difficult. Using ADOX in VB6 is a trivial process with
plenty of working examples on the web. At the moment I don't see any reason
why you shouldn't be able to manage it using C#, but if you are, and have an
immediate need ... you might consider using VB6 or even VBA/VBS to create a
separate utility to manage database changes. After all - it only needs to
run once and likely outside the main application. Once you have something
that works for your domain - translating to a dotNet solution shouldn't be
that difficult.
[I found that using DAO to be even easier to use to manage DDL in Jet
databases. I know - Arrrggggghhh! lol]
Not the best of solutions, but having a working utility (no matter how ugly)
might bring to light what the real issues are.
Go back to VB6? <cringe> Go back to DAO?? <double cringe> =) At least
you qualified your suggestion with words like "unsatisfactory" and "ugly"
LOL! I realize that sometimes that might be the only solution. I just hope
I don't have to.
Post by Ralph
Post by Brian Jahelka
My problem seems like this would be a VERY common problem that almost all
developers would face. Why isn't there a more standard way to do this? I
search the web and I read TONS of books, and no one really seems to want
to
Post by Brian Jahelka
talk about this subject.
The reason for the apparent "silence" on this subject is simply because
there IS no "standard way" to do it. Consider for a moment that there is no
"standard way" to store data or manipulate data in an application. Any
solution would be very specific for your domain and awkward if applied to
another. Just as other's solutions would be awkward if ported to yours.
The key of course is to have a database design that is amendable to
"changes". And then an Application Object model that is equally amendable to
"changes" - then any adjustments that need to be made can always be managed
by employing that first maxim of programming - "There is no problem that
can't be resolved with another layer of redirection". lol
-ralph
I would think someone could write an entire book on "best practices" or
"real world" examples of how best to maintain a database schema that needs to
evolve with its application. I have no problem with roll your own solutions,
I just find that the lack of documentation or even a REALLY good book on how
to do these things frustrating when it's not as easy to do as I ~think~ it
should be to do. =)
Loading...