473,387 Members | 1,771 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Nulls and Database objects

I have people telling me that I should set up objects for my tables, but I
am finding the Null problem makes that difficult.

It isn't a big problem if you are not updating the table, but if you are -
it is a real problem if you have Nullable fields. You can't always use a 0
or -1 to tell whether a field is null and dates are another problem. I
don't want to use some obscure date in the future for something like
"EndDate" or "DateTerminated" where there is no ending date or an employee
hasn't been terminated yet.

You don't have a problem if you use a field on an asp.net screen, as an
empty field would be taken as null. But that is not the same in an object
where you have to define a value for your fields.

I can see some real advantages to using objects for my tables, but they seem
to be outweighed by being unable to handle the nulls in either vb.net or c#.

I'd be curious to know how others are handling this problem (without using 0
or 1 or obscure data).

The problem is not reading the data from the table, but when changes are
made and you need to write it back, you need to know when a field is
supposed to be Null.

Thanks,

Tom
Nov 17 '05 #1
14 1883

"tshad" <ts**********@ftsolutions.com> wrote in message
news:ea**************@TK2MSFTNGP10.phx.gbl...
You don't have a problem if you use a field on an asp.net screen, as an
empty field would be taken as null. But that is not the same in an object
where you have to define a value for your fields.
You do?
I can see some real advantages to using objects for my tables, but they seem to be outweighed by being unable to handle the nulls in either vb.net or c#.
I'd be curious to know how others are handling this problem (without using 0 or 1 or obscure data).

The problem is not reading the data from the table, but when changes are
made and you need to write it back, you need to know when a field is
supposed to be Null.


I take it you are using simple data types for the "fields" on your objects.
If that's what you really want to do, you can define each private field as
"object" then cast it in the getter/setter. I don't know how big the
performance penalty is for "boxing" all those values, it'll certainly depend
on your application. We use objects to hold various information about our
"fields". We find it advantagous to be able to hold more information than
just the current value - for example the "old" value (as loaded from the
database), whether the field is loaded or not (some fields are lazy loaded),
and whether the field is null, among other things.

So, our code looks like this (method names reveal my Delphi background):

myObject.FirstName.AsString = "Scott";
myObject.LastName.AsString = "Roberts";
myObject.Salary.AsFloat = 250000.00; // haha!

I could also do:

myObject.Salary.AsString = SalaryEdit.Text; // conversion handled by
"AsString", handles "$", etc.
myObject.Salary.IsNull = true;

Just some ideas. Don't think that you're limited to:

private decimal _salary;
public decimal Salary
{
get {return _salary;}
set {_salary = value;}
}
Nov 17 '05 #2
"Scott Roberts" <sc***********@no-spam.intelebill.com> wrote in message
news:ea**************@TK2MSFTNGP14.phx.gbl...

"tshad" <ts**********@ftsolutions.com> wrote in message
news:ea**************@TK2MSFTNGP10.phx.gbl...
You don't have a problem if you use a field on an asp.net screen, as an
empty field would be taken as null. But that is not the same in an
object
where you have to define a value for your fields.
You do?


Actually, what I do is check for null coming from the database or check to
see if my field (textbox or label) is blank if going to the database.

For non-strings (int, decimal, money, dates) this is how I have to handle
it.

If the data coming from the database is Null, I leave the field blank. Then
when I write the data back and the field is blank, I send DBNull.Value like
so:

if salaryDesired.text = ""
.Add("@salaryDesired",SqlDbType.Money).value = DBNull.Value
else
.Add("@salaryDesired",SqlDbType.Money).value =
Regex.Replace(salaryDesired.text,"\$|\,","")
end if

I can't do that in an object as there is now in intermediate step.

I get the data from the database, put the data into the Objects private
variables (which can't be null). I then do whatever I am going to do on the
page and would now need to move the data back to the Object (again can't be
null) and then the data is moved from the Objects private variables to the
database record.

How do you tell if a value was a Null when you put it back?
I can see some real advantages to using objects for my tables, but they seem
to be outweighed by being unable to handle the nulls in either vb.net or

c#.

I'd be curious to know how others are handling this problem (without
using

0
or 1 or obscure data).

The problem is not reading the data from the table, but when changes are
made and you need to write it back, you need to know when a field is
supposed to be Null.


I take it you are using simple data types for the "fields" on your
objects.
If that's what you really want to do, you can define each private field as
"object" then cast it in the getter/setter. I don't know how big the
performance penalty is for "boxing" all those values, it'll certainly
depend
on your application. We use objects to hold various information about our
"fields". We find it advantagous to be able to hold more information than
just the current value - for example the "old" value (as loaded from the
database), whether the field is loaded or not (some fields are lazy
loaded),
and whether the field is null, among other things.


Keeping the old value would obviously be valuable. But do you do that for
all your fields?

For example, I have about 150 fields in one of my table records (mixture of
strings, ints, money and bits).

Do you set up each field as an object?

So, our code looks like this (method names reveal my Delphi background):

myObject.FirstName.AsString = "Scott";
myObject.LastName.AsString = "Roberts";
myObject.Salary.AsFloat = 250000.00; // haha!
Wouldn't that be nice. :)

I would do the same thing if I were setting up an object where the class
might be Position.

Then I would access my private variables as:

Position.FirstName = "Joe";
Position.Salary = 320000.00; // Thinking a little higher.

My class might be something like:
**********************************************
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using MyFunctions;

namespace FtsData
{
[Serializable]
public class Position
{
private int positionID = 0;
private string firstName = "";
private decimal Salary = 0;

public Position()
{
}

public Position(int PositionID)
{

}

public int AddRecord()
{
int rowsAffected = 0;
int iError = 0;
DbObject myDbObject = new DbObject();
SqlParameter[] parameters = {
new SqlParameter("@PositionID",SqlDbType.Int),
new SqlParameter("@FirstName",SqlDbType.VarChar,30),
new SqlParameter("@Salary",SqlDbType.Money) };

parameters[0].Value = positionID;
parameters[1].Value = firstName;
parameters[2].Value = salary;

try
{
iError = myDbObject.RunProcedure("AddPosition", parameters, ref
rowsAffected);
}
catch (SqlException sqle)
{
throw sqle;
}
}
// Properties

public int PositionID
{
get { return positionID; }
set { positionID = value; }
}

public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

public decimal Salary
{
get { return salary; }
set { salary = value; }
}
}
}
************************************************** *********************

Thanks,

Tom
I could also do:

myObject.Salary.AsString = SalaryEdit.Text; // conversion handled by
"AsString", handles "$", etc.
myObject.Salary.IsNull = true;

Just some ideas. Don't think that you're limited to:

private decimal _salary;
public decimal Salary
{
get {return _salary;}
set {_salary = value;}
}

Nov 17 '05 #3
i wrote a "NullHandler" class. By design, i decided for Value Types (int,
decimal, DataTime etc.) MaxValue indicates DBNull, for reference types, null
indicates DBNull.. when i get/set a value from/to database object
(DataReader, DataParameter etc.) i use NullHandler.. only boolean type cant
be null in my design. (because i didnt need. i hope you wont need too.)
here is the class.
using System;

namespace DataAccess

{

public sealed class NullHandler

{

private NullHandler()

{

}

public static void GetValueFromDbObject(object dbObjectValue, ref string
destination)

{

destination = dbObjectValue == DBNull.Value ? null : (string)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref int
destination)

{

destination = dbObjectValue == DBNull.Value ? int.MaxValue :
(int)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref decimal
destination)

{

destination = dbObjectValue == DBNull.Value ? decimal.MaxValue :
(decimal)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref DateTime
destination)

{

destination = dbObjectValue == DBNull.Value ? DateTime.MaxValue :
(DateTime)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref long
destination)

{

destination = dbObjectValue == DBNull.Value ? long.MaxValue :
(long)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref byte
destination)

{

destination = dbObjectValue == DBNull.Value ? byte.MaxValue :
(byte)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref object
destination, Type destinationType)

{

switch(destinationType.Name)

{

case "System.String" :

destination = dbObjectValue == DBNull.Value ? null : dbObjectValue;

break;

case "System.Int32" :

destination = dbObjectValue == DBNull.Value ? Int32.MaxValue :
dbObjectValue;

break;

case "System.Decimal" :

destination = dbObjectValue == DBNull.Value ? Decimal.MaxValue :
dbObjectValue;

break;

case "System.DateTime" :

destination = dbObjectValue == DBNull.Value ? DateTime.MaxValue :
dbObjectValue;

break;

case "System.Int64" :

destination = dbObjectValue == DBNull.Value ? Int64.MaxValue :
dbObjectValue;

break;

case "System.Byte" :

destination = dbObjectValue == DBNull.Value ? Byte.MaxValue : dbObjectValue;

break;

default :

if(destinationType.IsValueType)

throw new NotImplementedException("Converting from type '" +
dbObjectValue.GetType().Name + "' to '" + destinationType.Name + "' not
implemented..");

destination = dbObjectValue == DBNull.Value ? null : dbObjectValue;

break;

}

}

public static void SetDbObjectValueFromValue(string sourceValue, ref object
dbObjectValue)

{

if(sourceValue == null)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(int sourceValue, ref object
dbObjectValue)

{

if(sourceValue == int.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(decimal sourceValue, ref object
dbObjectValue)

{

if(sourceValue == decimal.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(DateTime sourceValue, ref
object dbObjectValue)

{

if(sourceValue == DateTime.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(long sourceValue, ref object
dbObjectValue)

{

if(sourceValue == long.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(byte sourceValue, ref object
dbObjectValue)

{

if(sourceValue == byte.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(object sourceValue, Type
sourceValueType, ref object dbObjectValue)

{

switch(sourceValueType.Name)

{

case "System.String" :

{

string val = (string)sourceValue;

if(val == null)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Int32" :

{

int val = (int)sourceValue;

if(val == int.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}
case "System.Decimal" :

{

decimal val = (decimal)sourceValue;

if(val == decimal.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.DateTime" :

{

DateTime val = (DateTime)sourceValue;

if(val == DateTime.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Int64" :

{

long val = (long)sourceValue;

if(val == long.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Byte" :

{

byte val = (byte)sourceValue;

if(val == byte.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

default :

if(sourceValueType.IsValueType)

throw new NotImplementedException("Converting from type '" +
dbObjectValue.GetType().Name + "' to '" + sourceValueType.Name + "' not
implemented.");

if(sourceValue == null)

dbObjectValue = DBNull.Value;

else

sourceValue = sourceValue;

break;

} // End Switch Statment

} // End Method Block

}

}

Here is how i use this class :

protected override void DoLoad(IDataReader rd)

{

this.itemName = (string)rd["ItemName"];

NullHandler.GetValueFromDbObject(rd["Description"], ref this.description);

NullHandler.GetValueFromDbObject(rd["ItemGroupId"], ref this.itemGroupId);

}


protected override void AppendSaveParameters(DbParameterCollection paramCol)

{

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("ItemName",
itemName) );

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("Description",
description) );

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("ItemGroupId",
itemGroupId) );

}

DataAccessHelper's ParameterHandler property is a kind of factory -
singleton (DataAccessHelper instantinates a specific ParameterHandler based
on "DataProvider" value in the application settings. (for example it
instantinates SqlParameterHandler class written by me.), and returns this
single instance everytime a parameter handler is requested.) here is a
method of SqlParameterHandler :

IDataParameter
DataAccess.Interfaces.IDbParameterHandler.GetInput ParameterFromValue(string
paramName, byte value)

{

IDataParameter param = new SqlParameter("@" + paramName, SqlDbType.TinyInt);

object obj = null;

NullHandler.SetDbObjectValueFromValue(value, ref obj);

param.Value = obj;

return param;

}

Hope this helps.. you can ask further.
Nov 17 '05 #4

"tshad" <ts**********@ftsolutions.com> wrote in message
news:OO**************@tk2msftngp13.phx.gbl...
"Scott Roberts" <sc***********@no-spam.intelebill.com> wrote in message
news:ea**************@TK2MSFTNGP14.phx.gbl... if salaryDesired.text = ""
.Add("@salaryDesired",SqlDbType.Money).value = DBNull.Value
else
.Add("@salaryDesired",SqlDbType.Money).value =
Regex.Replace(salaryDesired.text,"\$|\,","")
end if

I can't do that in an object as there is now in intermediate step.
Sure you can. It's the GUI's responsibility to set the business object
properties correctly. It's the BO's responsibility to persist the data
correctly.

if salaryDesired.Text = string.Empty
myObject.salaryDesired.IsNull = true;
else
myObject.salaryDesired.AsString = salaryDesired.Text;
I get the data from the database, put the data into the Objects private
variables (which can't be null).
Sure they can, if they are of type "object".
Keeping the old value would obviously be valuable. But do you do that for
all your fields?
Yes. It's how I know if a particular field needs to be persisted to the
database or not. I don't write fields to the DB that didn't change.
For example, I have about 150 fields in one of my table records (mixture of strings, ints, money and bits).
So? Are you writing an application for devices with limited memory? If so,
that makes a difference.
Do you set up each field as an object?


Yes.
Nov 17 '05 #5
> So? Are you writing an application for devices with limited memory? If so,
that makes a difference.


how about if you are writing a multi-client app like a web app? then it
makes difference.

and one thing about keeping old values : do you use dynamic sql? if not, how
do you send parameters (only changed fields)
Nov 17 '05 #6
This looks good. I assume this is similar to what Scott was talking about.

2 questions.

1. I have never used the Object type. Is it defined somewhere or is it
like a variant type that contains any type of data? I assumed that was the
case as you move any type of data into it.

2. How would you handle data that happened to be the Max Value of that
particular type?

For example, I assume that the MaxValue for byte is 255. I can see that
hitting the max value for decimal or long would be rare, but I can
definately see using 255 for a byte.

Thanks,

Tom

"The Crow" <q> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
i wrote a "NullHandler" class. By design, i decided for Value Types (int,
decimal, DataTime etc.) MaxValue indicates DBNull, for reference types,
null indicates DBNull.. when i get/set a value from/to database object
(DataReader, DataParameter etc.) i use NullHandler.. only boolean type cant
be null in my design. (because i didnt need. i hope you wont need too.)
here is the class.
using System;

namespace DataAccess

{

public sealed class NullHandler

{

private NullHandler()

{

}

public static void GetValueFromDbObject(object dbObjectValue, ref string
destination)

{

destination = dbObjectValue == DBNull.Value ? null :
(string)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref int
destination)

{

destination = dbObjectValue == DBNull.Value ? int.MaxValue :
(int)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref decimal
destination)

{

destination = dbObjectValue == DBNull.Value ? decimal.MaxValue :
(decimal)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref DateTime
destination)

{

destination = dbObjectValue == DBNull.Value ? DateTime.MaxValue :
(DateTime)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref long
destination)

{

destination = dbObjectValue == DBNull.Value ? long.MaxValue :
(long)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref byte
destination)

{

destination = dbObjectValue == DBNull.Value ? byte.MaxValue :
(byte)dbObjectValue;

}

public static void GetValueFromDbObject(object dbObjectValue, ref object
destination, Type destinationType)

{

switch(destinationType.Name)

{

case "System.String" :

destination = dbObjectValue == DBNull.Value ? null : dbObjectValue;

break;

case "System.Int32" :

destination = dbObjectValue == DBNull.Value ? Int32.MaxValue :
dbObjectValue;

break;

case "System.Decimal" :

destination = dbObjectValue == DBNull.Value ? Decimal.MaxValue :
dbObjectValue;

break;

case "System.DateTime" :

destination = dbObjectValue == DBNull.Value ? DateTime.MaxValue :
dbObjectValue;

break;

case "System.Int64" :

destination = dbObjectValue == DBNull.Value ? Int64.MaxValue :
dbObjectValue;

break;

case "System.Byte" :

destination = dbObjectValue == DBNull.Value ? Byte.MaxValue :
dbObjectValue;

break;

default :

if(destinationType.IsValueType)

throw new NotImplementedException("Converting from type '" +
dbObjectValue.GetType().Name + "' to '" + destinationType.Name + "' not
implemented..");

destination = dbObjectValue == DBNull.Value ? null : dbObjectValue;

break;

}

}

public static void SetDbObjectValueFromValue(string sourceValue, ref
object dbObjectValue)

{

if(sourceValue == null)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(int sourceValue, ref object
dbObjectValue)

{

if(sourceValue == int.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(decimal sourceValue, ref
object dbObjectValue)

{

if(sourceValue == decimal.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(DateTime sourceValue, ref
object dbObjectValue)

{

if(sourceValue == DateTime.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(long sourceValue, ref object
dbObjectValue)

{

if(sourceValue == long.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(byte sourceValue, ref object
dbObjectValue)

{

if(sourceValue == byte.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = sourceValue;

}

public static void SetDbObjectValueFromValue(object sourceValue, Type
sourceValueType, ref object dbObjectValue)

{

switch(sourceValueType.Name)

{

case "System.String" :

{

string val = (string)sourceValue;

if(val == null)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Int32" :

{

int val = (int)sourceValue;

if(val == int.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}
case "System.Decimal" :

{

decimal val = (decimal)sourceValue;

if(val == decimal.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.DateTime" :

{

DateTime val = (DateTime)sourceValue;

if(val == DateTime.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Int64" :

{

long val = (long)sourceValue;

if(val == long.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

case "System.Byte" :

{

byte val = (byte)sourceValue;

if(val == byte.MaxValue)

dbObjectValue = DBNull.Value;

else

dbObjectValue = val;

break;

}

default :

if(sourceValueType.IsValueType)

throw new NotImplementedException("Converting from type '" +
dbObjectValue.GetType().Name + "' to '" + sourceValueType.Name + "' not
implemented.");

if(sourceValue == null)

dbObjectValue = DBNull.Value;

else

sourceValue = sourceValue;

break;

} // End Switch Statment

} // End Method Block

}

}

Here is how i use this class :

protected override void DoLoad(IDataReader rd)

{

this.itemName = (string)rd["ItemName"];

NullHandler.GetValueFromDbObject(rd["Description"], ref this.description);

NullHandler.GetValueFromDbObject(rd["ItemGroupId"], ref this.itemGroupId);

}


protected override void AppendSaveParameters(DbParameterCollection
paramCol)

{

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("ItemName",
itemName) );

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("Description",
description) );

paramCol.Add(
DataAccessHelper.ParameterHandler.GetInputParamete rFromValue("ItemGroupId",
itemGroupId) );

}

DataAccessHelper's ParameterHandler property is a kind of factory -
singleton (DataAccessHelper instantinates a specific ParameterHandler
based on "DataProvider" value in the application settings. (for example it
instantinates SqlParameterHandler class written by me.), and returns this
single instance everytime a parameter handler is requested.) here is a
method of SqlParameterHandler :

IDataParameter
DataAccess.Interfaces.IDbParameterHandler.GetInput ParameterFromValue(string
paramName, byte value)

{

IDataParameter param = new SqlParameter("@" + paramName,
SqlDbType.TinyInt);

object obj = null;

NullHandler.SetDbObjectValueFromValue(value, ref obj);

param.Value = obj;

return param;

}

Hope this helps.. you can ask further.

Nov 17 '05 #7
> This looks good. I assume this is similar to what Scott was talking
about.

2 questions.

1. I have never used the Object type. Is it defined somewhere or is it
like a variant type that contains any type of data? I assumed that was
the case as you move any type of data into it.
actually, i didnt ever used object type overload. i wrote it just for case,
when i didnt wrote an overload for a type. but in my project, i didnt needed
that method yet.
2. How would you handle data that happened to be the Max Value of that
particular type?

For example, I assume that the MaxValue for byte is 255. I can see that
hitting the max value for decimal or long would be rare, but I can
definately see using 255 for a byte.


this made me think too, but i didnt needed the value "255" for any byte
field too. but if i would need, it shows byte data type is not big enough
for that data, because when i werent used null handler and byte type, after
using 255, 256 wont be possible too. so think 254 is your limit for byte,
rather then 255. but if there is a real deal (for example you have to deal a
value that comes from a part of computer system), you can choose not using
NullHandler for that particular field and acces it directly.
Nov 17 '05 #8

"The Crow" <q> wrote in message
news:OB**************@TK2MSFTNGP12.phx.gbl...
and one thing about keeping old values : do you use dynamic sql? if not, how do you send parameters (only changed fields)


Yes, dynamic sql
Nov 17 '05 #9
do you think its good? did u measure performance?
Nov 17 '05 #10

"The Crow" <q> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
do you think its good? did u measure performance?


I assume you are referring to the ability of most DBs to cache execution
plans and reuse them if the same SQL statment is issued multiple times.

There are trade-offs to every decision. We are aware of the above fact
(applies to SQL Server and Oracle for sure) and decided to go with dynamic
SQL anyway. The advantages we see are:

1. Concurrency ("last save wins" is sufficient for us if only changed fields
are saved).
2. Less DB access (no SQL generated at all if no fields changed, regardless
of how many times the user clicks "Save")
3. Smaller SQL commands (if only 1 of 150 fields changed, the SQL generated
is very small).
4. For batch operations, it's always the same field(s) changing so the same
3 or 4 SQL statments will be dynamically generated and statement caching is
effective.
Nov 17 '05 #11

"tshad" <ts**********@ftsolutions.com> wrote in message
news:OO**************@tk2msftngp13.phx.gbl...
"Scott Roberts" <sc***********@no-spam.intelebill.com> wrote in message
news:ea**************@TK2MSFTNGP14.phx.gbl...

I take it you are using simple data types for the "fields" on your
objects.
If that's what you really want to do, you can define each private field
as
"object" then cast it in the getter/setter. I don't know how big the
performance penalty is for "boxing" all those values, it'll certainly
depend
on your application. We use objects to hold various information about our
"fields". We find it advantagous to be able to hold more information than
just the current value - for example the "old" value (as loaded from the
database), whether the field is loaded or not (some fields are lazy
loaded),
and whether the field is null, among other things.


I am looking at the Crow's class and like how it's done.

But that one also uses a one dimensioned simple variant type of data to hold
the value.

How would you change my class to have old values and a field to hold whether
it is null or not?

Would you set it up a multidimension variable or as a complex type of
object/structure?

I am just trying to look at different possibilities before going too much
farther with my objects if there is (and I am sure there is) a better way to
handle it and then have to reprogram it later.

Thanks,

Tom
My class might be something like:
**********************************************
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using MyFunctions;

namespace FtsData
{
[Serializable]
public class Position
{
private int positionID = 0;
private string firstName = "";
private decimal Salary = 0;

public Position()
{
}

public Position(int PositionID)
{

}

public int AddRecord()
{
int rowsAffected = 0;
int iError = 0;
DbObject myDbObject = new DbObject();
SqlParameter[] parameters = {
new SqlParameter("@PositionID",SqlDbType.Int),
new SqlParameter("@FirstName",SqlDbType.VarChar,30),
new SqlParameter("@Salary",SqlDbType.Money) };

parameters[0].Value = positionID;
parameters[1].Value = firstName;
parameters[2].Value = salary;

try
{
iError = myDbObject.RunProcedure("AddPosition", parameters, ref
rowsAffected);
}
catch (SqlException sqle)
{
throw sqle;
}
}
// Properties

public int PositionID
{
get { return positionID; }
set { positionID = value; }
}

public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

public decimal Salary
{
get { return salary; }
set { salary = value; }
}
}
}
************************************************** *********************

Thanks,

Tom

I could also do:

myObject.Salary.AsString = SalaryEdit.Text; // conversion handled by
"AsString", handles "$", etc.
myObject.Salary.IsNull = true;

Just some ideas. Don't think that you're limited to:

private decimal _salary;
public decimal Salary
{
get {return _salary;}
set {_salary = value;}
}


Nov 17 '05 #12
thanks for your answer. it seems to be wise.
Nov 17 '05 #13

"tshad" <ts**********@ftsolutions.com> wrote in message
news:%2******************@TK2MSFTNGP09.phx.gbl...
How would you change my class to have old values and a field to hold whether it is null or not?

Would you set it up a multidimension variable or as a complex type of
object/structure?


Basically, we have a SBSFieldList class (just a wrapper around ArrayList
with some convenience methods) that holds a list of "SBSField" objects (or
objects derived from SBSField - e.g. SBSStringField).

public class MyClass
{
MyFieldListClass _fields = new MyFieldListClass();

public MyClass()
{
// Fill _fields with field objects.
}

public SBSStringField FirstName
{
get {return _fields.FieldByName("firstname");}
}
}

And you access the property like this:

myObject.FirstName.AsString = "Scott";
myObject.FirstName.IsNull = true; // Set the first name to null value.

Note: We don't actually do "FieldByName" and scan the list for the proper
field object every time you access a property, that would be slow. There are
integer array indexes stored for each property to speed things up, but this
is simpler for demo purposes. And you'd really want the field list defined
in a base class and populated by the derived classes. This allows the base
class to have access to the fields without the need for reflection, etc.
Nov 17 '05 #14
Still a little confused on what you are doing.

But it is probably a little more that I can do at the moment.

Thanks,

Tom
"Scott Roberts" <sc***********@no-spam.intelebill.com> wrote in message
news:uG**************@TK2MSFTNGP12.phx.gbl...

"tshad" <ts**********@ftsolutions.com> wrote in message
news:%2******************@TK2MSFTNGP09.phx.gbl...
How would you change my class to have old values and a field to hold

whether
it is null or not?

Would you set it up a multidimension variable or as a complex type of
object/structure?


Basically, we have a SBSFieldList class (just a wrapper around ArrayList
with some convenience methods) that holds a list of "SBSField" objects (or
objects derived from SBSField - e.g. SBSStringField).

public class MyClass
{
MyFieldListClass _fields = new MyFieldListClass();

public MyClass()
{
// Fill _fields with field objects.
}

public SBSStringField FirstName
{
get {return _fields.FieldByName("firstname");}
}
}

And you access the property like this:

myObject.FirstName.AsString = "Scott";
myObject.FirstName.IsNull = true; // Set the first name to null value.

Note: We don't actually do "FieldByName" and scan the list for the proper
field object every time you access a property, that would be slow. There
are
integer array indexes stored for each property to speed things up, but
this
is simpler for demo purposes. And you'd really want the field list defined
in a base class and populated by the derived classes. This allows the base
class to have access to the fields without the need for reflection, etc.

Nov 17 '05 #15

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

Similar topics

3
by: Thomas Coleman | last post by:
I have been playing around with 2.0 and I'm trying clarify a few things about generics and data access. I was hoping to be able to do something like this with nullable types: int? foo = null; ...
17
by: Raziq Shekha | last post by:
Hello everyone, SQL Server 2000. I have a database in which there are several objects which have ansi nuls and quoted identifier turned ON. Is there a way I can generate a script which: (1)...
5
by: Robert Stearns | last post by:
Either I missed something, or ALTER TABLE does not have this capability. Is there any way of doing it except DROPping all constraints which mention this table, EXPORTing the data, DROPping the...
13
by: jt | last post by:
I can't seem to find a way to concatenate strings that have nulls within the string. I have a string that I need another string that has nulls in it and what to append the 2nd string, 3 string...
3
by: Simon | last post by:
Hi all, Do you think the best way to avoid the problems of nulls in the database is just to provide default values via the db schema? Alternatively, is it better to allow nulls, seeing as the...
5
by: Woody Splawn | last post by:
I have some code that looks like this: Dim SSN, LName, FName, M As String mySqlConnection = New SqlConnection(myConnectionString) Dim sql_Command As New SqlCommand( _ "Select SSN, LName, FName,...
12
by: Brian Henry | last post by:
first question... I have a flat file which unfortinuatly has columns seperated by nulls instead of spaces (a higher up company created it this way for us) is there anyway to do a readline with this...
0
by: dmac | last post by:
Hi, Im real new at this so be gentle. I want to create a customer object based on the results of an sql query to the customers table, ie one object per row, and then add each of these objects to an...
8
by: markjerz | last post by:
Hi, I basically have two tables with the same structure. One is an archive of the other (backup). I want to essentially insert the data in to the other. I use: INSERT INTO table ( column,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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

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