Refer to the field by name???

F

Frank Rizzo

I have the following code:

SqlDataReader dr;
SqlCommand sc = new SqlCommand("SELECT * FROM Articles", oConn);
oConn.Open();
dr = sc.ExecuteReader();

How can I now refer to the fields in the SqlDataReader by name, like
dr.Fields("Title") or something like that.

Because the only thing I am seeing is dr.GetString(i), where i is the
ordinal value.

Is it something simple that I have simply overlooked?

Thanks.
 
M

Miha Markic

Hi Frank,

dr.GetOrdinal(columnname) returns the index of the column which you might
use in other methods.
 
I

IbrahimMalluf

Hello All

The problem with using string lookups is that they require more time and
resources. In an Iterative situation, performance can degrade considerably.
If you already know the field names and the order they will appear in the
result set at design time then use enumerators instead of string lookups or
'Magic Numbers"

Example:

Public Enum People
PersonID = 0
FirstName=1
LastName = 2
etc...
End Enum

MyFirstName = dr.Fields(People.FirstName)

You retain the speed of integer indexes and get the readability of text
based names.



--
Ibrahim Malluf
http://www.malluf.com
==============================================
MCS Data Services Code Generator
http://64.78.34.175/mcsnet/DSCG/Announcement.aspx
==============================================
Pocket PC Return On Investment Calculator
Free Download http://64.78.34.175/mcsnet/kwickKalk1.aspx
 
W

William Ryan

Bill Vaughn has a really cool idea for this. Create an Enum and have the
Enum member names be the same as the field names. There's a GetOrdinal
method you can use, but as he's pointed out, the compiler needs to resolve
getordinal before it can reference it. If you use his enum method, then it
only has to resolve it once which can make it much faster.
 
F

Frank Rizzo

IbrahimMalluf said:
Hello All

The problem with using string lookups is that they require more time and
resources. In an Iterative situation, performance can degrade considerably.
If you already know the field names and the order they will appear in the
result set at design time then use enumerators instead of string lookups or
'Magic Numbers"

Example:

Public Enum People
PersonID = 0
FirstName=1
LastName = 2
etc...
End Enum

MyFirstName = dr.Fields(People.FirstName)

You retain the speed of integer indexes and get the readability of text
based names.

Thanks (as well as to the guy below suggesting the same idea).
I normally do exactly what you've suggested. However, in this case (and
future cases), I am cranking out a quickie test app where going to the
expense of creating an enum is simply not worth it.
 
M

Miha Markic

Hi Bill,

The drawback of this strategy would be that you'll have to
a) sync enums and columns order (modifications....)
b) you can't use select * from as you never know the columns order

Otherwise, yes, it is certainly the fastest.
 
K

Kathleen Dollard

Frank,

Try enums. They are easy to maintain if you don't explicitly give the
values.

Enum CustomerFields
CustomerID
CustomerFirstName
CustomerLastName
End Enum

dr.Fields(CustomerFields.CustomerFirstName)

The cool thing about this approach is that you have great autocomplete
support so you will type very little.

Kathleen
 
B

Bill Styles

Kathleen Dollard said:
Frank,

Try enums. They are easy to maintain if you don't explicitly give the
values.

Enum CustomerFields
CustomerID
CustomerFirstName
CustomerLastName
End Enum

dr.Fields(CustomerFields.CustomerFirstName)

The cool thing about this approach is that you have great autocomplete
support so you will type very little.

If you take this approach would it also make sense to build your Select
statement dynamically from the enum rather than using Select * or trying to
keep the field list in the Select and the enum synchronized?
 
K

Kathleen Dollard

Bill,

There is a different reason to avoid SELECT * in SQL Server. To be honest I
haven't followed up on this, but as I heard it from Kinberly Tripp, I
assumed it was correct SQL Server lore... The Server can't optimize
statements based on wildcards, but need an explicit file list to work their
magic.

I use code gen for this kind of stuff, so the maintenance is not excessive
(both the stored proc asn the enum from the same list based on the table
columns). Building the stored proc from the enum is conceivable, but
difficult. If you're using dynmaic SQL (do you want that speech now?) then
iterating through the enum is not a cheap operation. I guess if you're
leaning that way you might also consider creating a series of variables, one
for the position of each column. You could then use GetOrdinal to determine
the position once and iterate through your records.

I hate strings becuase the compiler can't help you. It's "magic" as Ibrahim
pointed out, and its resolved at runtime. If you're doing it by hand, you'd
still need a fairly dynamic database to be making many changes. Every way
you can leverage the compiler to insure you get compiler errors (cheap to
fix) rather than logic errors (expensive to fix) is a good thing.

If you like strings, you can create constants to represent them, which at
least eases some of the maintenance burderns. Unfortunately it turns into a
lot of string constants in even medium sized databases.

Kathleen

If you're a beginner (you're sig) - if you're not working in ASP.NET, and
half the time when you are, the extra code to manage the DataReader (instead
of the DataSet) is hard to justify. Don't overlook the
 
F

Frank Rizzo

Kathleen said:
Bill,

There is a different reason to avoid SELECT * in SQL Server. To be honest I
haven't followed up on this, but as I heard it from Kinberly Tripp, I
assumed it was correct SQL Server lore... The Server can't optimize
statements based on wildcards, but need an explicit file list to work their
magic.

That's right. Sybase actually resolves wildcards in stored procs at
their creation. So if you have select * from tbl, it will convert it to
select f1,f2,f3,... from tbl immediately.
I use code gen for this kind of stuff, so the maintenance is not excessive

What code gen do you use?
 
B

Bill Styles

Kathleen Dollard said:
Bill,

There is a different reason to avoid SELECT * in SQL Server. To be
honest I haven't followed up on this, but as I heard it from Kinberly
Tripp, I assumed it was correct SQL Server lore... The Server can't
optimize statements based on wildcards, but need an explicit file
list to work their magic.

Understood; I never use Select * myself for that exact reason but that's
what the question you responded to used.
I use code gen for this kind of stuff, so the maintenance is not
excessive (both the stored proc asn the enum from the same list based
on the table columns).

That makes sense and would be the way to go. It's just that I've seen a
couple of people suggest using an Enum instead of the GetOrdinal method and
was thinking that if you are maintaining an app that uses SQL strings
without that sort of code generation available then you need to synchronize
the enum with the select. I toyed with the idea and it seemed like I could
build the field list pretty easily and that way I'd never have to worry
about keeping the two matching.
Building the stored proc from the enum is
conceivable, but difficult. If you're using dynmaic SQL (do you want
that speech now?)

<g> no speech needed but I have a number of cases where the same app has to
run against SQL, Oracle, Access and possibly other backend databases.
Building SQL strings often makes that easier than dealing with different SP
capabilities.
then iterating through the enum is not a cheap operation.

Yes, but it'd only have to be done once at the start of the application and
if it saves one instance of missing updating things properly or relieves a
maintenance programmer from having to know about the requirement the
tradeoff might be worth it.
I guess if you're leaning that way you might also consider
creating a series of variables, one for the position of each column.
You could then use GetOrdinal to determine the position once and
iterate through your records.

That's what the enum gives me isn't it?

I hate strings becuase the compiler can't help you. It's "magic" as
Ibrahim pointed out, and its resolved at runtime. If you're doing it
by hand, you'd still need a fairly dynamic database to be making many
changes.

True, but all it takes is one missed change to potentially cause a lot of
trouble.
Every way you can leverage the compiler to insure you get
compiler errors (cheap to fix) rather than logic errors (expensive to
fix) is a good thing.

No argument there. All of this is just a 'gedanken experiment' on my part.
I'm not sure I'd ever use the technique but am curious what the drawbacks
might be so this has been very useful.
If you like strings, you can create constants to represent them,
which at least eases some of the maintenance burderns. Unfortunately
it turns into a lot of string constants in even medium sized
databases.

Again, I think the Enum dynamically translated to a list of fields would
work...

private enum dbfields {
field1,
field2,
field3,
field4
}

private string GetFieldList() {
dbfields dbf=dbfields.field1;
string s="";
foreach (string f in Enum.GetNames(dbf.GetType()))
s=s + "[" + f + "],";
return s.Substring(0,s.Length-1);
}

string s="Select " + GetFieldList() + " From mytable";

Kathleen

If you're a beginner (you're sig) -

C# newbie, I have used other languages quite a bit over the years. Always
looking to learn new/better techniques though.
if you're not working in ASP.NET,

Mostly not, at least not yet. Gotta get more familiar with C# and the
framework before adding the complexities of ASP.Net on top of that.
and half the time when you are, the extra code to manage the
DataReader (instead of the DataSet) is hard to justify. Don't
overlook the

That got cut off but I generally do use the DataSet or a DataTable rather
than a DataReader. I still need to run a query to get the data somehow
though! <g>
 
K

Kathleen Dollard

Frank,
That's right.

Thanks to the folks that confirmed the SQL behavior. I was posting that and
thought "now why do I think that's true?"
What code gen do you use?

My own. The book is quite literally "at the printer" and is called Code
Generation in Microsoft .NET (Apress).

The short answer to why is that today's code generators don't meet my
non-negotiables - the programmer is in control, metadata (app info) and
technology are separated, you can regenerate any time (including after all
project members won the lottery and left for Tahiti) with a single button
click, handcrafted (human written) code is included, respected, sacred,
isolated, and protected, and finally code generated applications are equal
or better quality than manually built applications in every way.

Code generation is going to crash in and change our worlds. I want
programmers to understand it, know they can do it themselves, and be ready
to use it effectively. I am unwilling to abdicate code responsibility to any
third party.

Anyway, it was a really tough book to write and that's why I was AWOL here
for about a year.

Kathleen
 
K

Kathleen Dollard

Bill,
Yes, but it'd only have to be done once at the start of the application and
if it saves one instance of missing updating things properly or relieves a
maintenance programmer from having to know about the requirement the
tradeoff might be worth it.

If you don't have too many unique sets to haul around during the app that's
a good choice. Sorry about the multi-platform problems driving you to
dynamic SQL. I hate to mention code gen so many times in one thread, but
someplace down the road you might want to explore that as an effective way
to build stored procedures for multiple backends. Sounds like you already
know that any dynamic SQL at all undermines your ability to restrict user
permissions, and therefore opens up security a litttle bit.
That's what the enum gives me isn't it?

Here's my thought - and the effectiveness of this depends on the number of
rows you've got each time you hit the database. It would work with stored
procs, where your dynamic SQL from the enum makes sense for dynamic SQL.
Create variables for the fields you expect - the ones you're going to use.
Grab the schema too and cruise it for the anticipated names (alternatively,
use GetOrdinal). Set the variables to the real time, accurate field
ordinals, and do the rest of your access through the faster ordinal access.
True, but all it takes is one missed change to potentially cause a lot of
trouble.

I have maintained a large system (in VB6 days) that used enums for
positioning. The maintenance was only difficult where I had to rip out
absolute numbers. Someone thought that was more reliable. It is when the
numbers your representing have absolute meaning, it is far less reliable
when the numbers are inherently sequential. Yes, we did sometimes have
issues in the enum lists - but they were quickly solved. Course the DBA on
that project didn't go rearranging fields on a whim, either.

One misspelled string or changed field name causes a lot of chaos too.
No argument there. All of this is just a 'gedanken experiment' on my part.
I'm not sure I'd ever use the technique but am curious what the drawbacks
might be so this has been very useful.

That's why we're here, right? Solving other people's problems in our head
before we run into them as our problem speeds things up <g>

Kathleen


Bill Styles said:
Kathleen Dollard said:
Bill,

There is a different reason to avoid SELECT * in SQL Server. To be
honest I haven't followed up on this, but as I heard it from Kinberly
Tripp, I assumed it was correct SQL Server lore... The Server can't
optimize statements based on wildcards, but need an explicit file
list to work their magic.

Understood; I never use Select * myself for that exact reason but that's
what the question you responded to used.
I use code gen for this kind of stuff, so the maintenance is not
excessive (both the stored proc asn the enum from the same list based
on the table columns).

That makes sense and would be the way to go. It's just that I've seen a
couple of people suggest using an Enum instead of the GetOrdinal method and
was thinking that if you are maintaining an app that uses SQL strings
without that sort of code generation available then you need to synchronize
the enum with the select. I toyed with the idea and it seemed like I could
build the field list pretty easily and that way I'd never have to worry
about keeping the two matching.
Building the stored proc from the enum is
conceivable, but difficult. If you're using dynmaic SQL (do you want
that speech now?)

<g> no speech needed but I have a number of cases where the same app has to
run against SQL, Oracle, Access and possibly other backend databases.
Building SQL strings often makes that easier than dealing with different SP
capabilities.

then iterating through the enum is not a cheap operation.

Yes, but it'd only have to be done once at the start of the application and
if it saves one instance of missing updating things properly or relieves a
maintenance programmer from having to know about the requirement the
tradeoff might be worth it.
I guess if you're leaning that way you might also consider
creating a series of variables, one for the position of each column.
You could then use GetOrdinal to determine the position once and
iterate through your records.

That's what the enum gives me isn't it?

I hate strings becuase the compiler can't help you. It's "magic" as
Ibrahim pointed out, and its resolved at runtime. If you're doing it
by hand, you'd still need a fairly dynamic database to be making many
changes.

True, but all it takes is one missed change to potentially cause a lot of
trouble.
Every way you can leverage the compiler to insure you get
compiler errors (cheap to fix) rather than logic errors (expensive to
fix) is a good thing.

No argument there. All of this is just a 'gedanken experiment' on my part.
I'm not sure I'd ever use the technique but am curious what the drawbacks
might be so this has been very useful.
If you like strings, you can create constants to represent them,
which at least eases some of the maintenance burderns. Unfortunately
it turns into a lot of string constants in even medium sized
databases.

Again, I think the Enum dynamically translated to a list of fields would
work...

private enum dbfields {
field1,
field2,
field3,
field4
}

private string GetFieldList() {
dbfields dbf=dbfields.field1;
string s="";
foreach (string f in Enum.GetNames(dbf.GetType()))
s=s + "[" + f + "],";
return s.Substring(0,s.Length-1);
}

string s="Select " + GetFieldList() + " From mytable";

Kathleen

If you're a beginner (you're sig) -

C# newbie, I have used other languages quite a bit over the years. Always
looking to learn new/better techniques though.
if you're not working in ASP.NET,

Mostly not, at least not yet. Gotta get more familiar with C# and the
framework before adding the complexities of ASP.Net on top of that.
and half the time when you are, the extra code to manage the
DataReader (instead of the DataSet) is hard to justify. Don't
overlook the

That got cut off but I generally do use the DataSet or a DataTable rather
than a DataReader. I still need to run a query to get the data somehow
though! <g>
 
B

Bill Styles

Create variables for the fields you expect -
the ones you're going to use. Grab the schema too and cruise it for
the anticipated names (alternatively, use GetOrdinal). Set the
variables to the real time, accurate field ordinals, and do the rest
of your access through the faster ordinal access.

That'd work too; I like the enum idea only because of the intellisense and
the ability to specify them in argument lists/etc. Perhaps a structure or
other object with the individual variables would work as well and I'll have
to play with the ideas to see what works best for me.

I've seen & used codegen utilities before and agree they are great but the
ones I'm familiar with are more for just first-pass skeleton code creation.
What you have described sounds like a step beyond that allowing more use in
the maintenance phase of a project lifetime and that's another idea I'll
need to play around with.

Just when you think you've got a handle on it some new idea always comes
along! Thanks for the feedback.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top