Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / January 2008

Tip: Looking for answers? Try searching our database.

Get properties in native order for DbLinq

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Andrus - 05 Jan 2008 14:38 GMT
I need to get type t properies in the native order as they appear in class
definition .cs file.
Type t has full-property constructor whose parameters are all properties in
native order.

I tried

public static PropertyInfo[] GetProjectionDataInNativeOrder(Type t) {
 PropertyInfo[] props = t.GetProperties();
 return props;
}

First call returns properties in proper order.
After some objects of type t are created and their properties accessed
GetProperties() returns props in different order.

How to force this code to return properties in native order always ?

How to change this code so it caches result of first GetProperties() call
for every type and returns previous value returned by GetProperties() ?
Is the property order always native in this case ?

Or any other soution ?

Andrus.
Jon Skeet [C# MVP] - 05 Jan 2008 14:50 GMT
> I need to get type t properies in the native order as they appear in class
> definition .cs file.

You can't. There is absolutely no guarantee that the C# compiler will
leave anything in the IL to indicate the original order.

If you need a particular order, you'll need to specify it in the class.

<snip>

> Or any other soution ?

Yes - make your code less fragile by having another indicator of the
order of the constructors. Using the order in which GetProperties
returns the properties is a recipe for disaster.

The docs for GetProperties make this very clear:

<quote>
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
</quote>

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Andrus - 05 Jan 2008 17:59 GMT
Jon,

> If you need a particular order, you'll need to specify it in the class.

I found two ways to solve:

1. Extracted full-property constructor parameter names.
They are same as class properties in my generated code.
.Net must return constructor parameters in native order.
Is this possible and reasonable ?

2. Add column attribute like Ordinal=   to every property.

Can anybody point how Linq-SQL solves this issue? I havent found any Ordinal
attribute in ColumnAttribute class in MSDN help.

> Yes - make your code less fragile by having another indicator of the
> order of the constructors. Using the order in which GetProperties
[quoted text clipped - 8 lines]
> order varies.
> </quote>

DbLinq calls GetProperties() before every object retrieve. I have
optimization turned off is VCS2008).
I found that in this case first GetProperties() invocation returns
properties in native order.
So I created the following method as quick hack to move forward.  Other
methods above seems to require large re-write of code.

Any better idea ?

Andrus.

static Dictionary<Type, PropertyInfo[]> Dict = new Dictionary<Type,
PropertyInfo[]>();

public static PropertyInfo[] GetPropertiesInNativeOrder(Type t) {
PropertyInfo[] props;
if (Dict.ContainsKey(t))
 props = Dict[t];
else {
 props = t.GetProperties();
 Dict.Add(t, props);
}
return props;
}
Jon Skeet [C# MVP] - 05 Jan 2008 19:12 GMT
> > If you need a particular order, you'll need to specify it in the class.
>
[quoted text clipped - 4 lines]
> .Net must return constructor parameters in native order.
> Is this possible and reasonable ?

Possible. Not great though - it looks like parameter names are
preserved even for release builds, but I don't know if that's
guaranteed.

> 2. Add column attribute like Ordinal=   to every property.

Or attributes to the constructor parameters.

> Can anybody point how Linq-SQL solves this issue? I havent found any Ordinal
> attribute in ColumnAttribute class in MSDN help.

What makes you think LINQ to SQL has this issue to start with?

> DbLinq calls GetProperties() before every object retrieve. I have
> optimization turned off is VCS2008).
> I found that in this case first GetProperties() invocation returns
> properties in native order.
> So I created the following method as quick hack to move forward.  Other
> methods above seems to require large re-write of code.

Avoiding a large rewrite because something happens to work at the
moment despite an explicit warning in the documentation not to rely on
something is a really bad idea.

> Any better idea ?

Why do you have this issue in the first place? Are the objects
immutable? If not, can't you just set the properties directly?

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Andrus - 05 Jan 2008 22:01 GMT
> Possible. Not great though - it looks like parameter names are
> preserved even for release builds, but I don't know if that's
> guaranteed.

All .net framework method parameter  names are documented.
There are some languages in .net like Python  which allow to use named
parameters for methods.

So parameter name saving *is* guaranteed.

>> Can anybody point how Linq-SQL solves this issue? I havent found any
>> Ordinal
>> attribute in ColumnAttribute class in MSDN help.
>
> What makes you think LINQ to SQL has this issue to start with?

Linq-SQL generated entity class code has probably full parameter
constructors.
To instantiate entity objects, Linq-SQL driver must convert columns returned
from SQL SELECT
command to constructor parameters.

> Why do you have this issue in the first place? Are the objects
> immutable? If not, can't you just set the properties directly?

I'm trying to fix DbLinq driver code.
Linq driver does not know property names and even entity type names.
All information must be determined at runtime.

I have found also two additional ways:

1. Set every property separately, remove parametherized constructor.
2. Sort constructor parameters in alphabetical order.

Really do'nt know which is the best way to go so trying this dirty hack.

Andrus.
Jon Skeet [C# MVP] - 05 Jan 2008 22:51 GMT
> > Possible. Not great though - it looks like parameter names are
> > preserved even for release builds, but I don't know if that's
[quoted text clipped - 5 lines]
>
> So parameter name saving *is* guaranteed.

Right. In that case, that's not a *hugely* bad way round it.

> > What makes you think LINQ to SQL has this issue to start with?
>
> Linq-SQL generated entity class code has probably full parameter
> constructors.

No, it doesn't. I've just checked.

> To instantiate entity objects, Linq-SQL driver must convert columns returned
> from SQL SELECT command to constructor parameters.

No, it doesn't. I don't know exactly what it *does* do (it seems to
avoid properties too) but there's no constructor with parameters for it
to call.

> > Why do you have this issue in the first place? Are the objects
> > immutable? If not, can't you just set the properties directly?
>
> I'm trying to fix DbLinq driver code.
> Linq driver does not know property names and even entity type names.
> All information must be determined at runtime.

None of that stops you from setting properties.

> I have found also two additional ways:
>
> 1. Set every property separately, remove parametherized constructor.
> 2. Sort constructor parameters in alphabetical order.
>
> Really do'nt know which is the best way to go so trying this dirty hack.

Setting properties is by far the cleanest way here, IMO.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Andrus - 06 Jan 2008 09:50 GMT
>> So parameter name saving *is* guaranteed.
>Right. In that case, that's not a *hugely* bad way round it.

I subclass entity base classes to add custom properties by compiling
assembly at runtime.
I need also to add business methods like

public static Customer FindById(string id) {
  var q = (from k in Default.Db.Customers
              where k.Id == id
              select k).SingleOrDefault();
   return q;
}

to those dynamic-subclassed entities at design time.

At design time I do'nt know all Customer properties. So I cannot create cs
file containing full-property constructor and thus cannot use subclassing.

Partial assemblies are not supported in .net. Using partial classes requires
compiling business method source code at runtime. This seems not reasonable.

So Adding FindById() to full-parameter constructor class requires creating
separate not-inherited  business logic class  for every entity. This makes
application unnessecarily complicated.

Is this reasonable ?

> No, it doesn't. I don't know exactly what it *does* do (it seems to
> avoid properties too) but there's no constructor with parameters for it
> to call.

Let's say we have

Db.Customers.ToList()

expression.

Linq-SQL driver must use GetProperties() to find all Customer properties
having ColumnAttribute attributes.
Then it should invoke parameteless constructor to create new Customer entity
and use reflection to set new entity properties, one-by-one.
I see no other way.

However in my case this requires re-writing parts of DbLinq driver code.

> Setting properties is by far the cleanest way here, IMO.

I'm in initial stage of development called "probing".
I do'nt have enough resources required to re-write, debug and support
property approach in this stage.

I'm planning to create application quick prototype.
Results of this probe determine will we move to .NET or  start looking
something other.

So creating separate business classes for every entity class and using quick
dirty hack to fix
GetProperties() ordering issue seems to be optimal in this case, is'nt it ?

Andrus.
Jon Skeet [C# MVP] - 06 Jan 2008 12:45 GMT
> >> So parameter name saving *is* guaranteed.
> >Right. In that case, that's not a *hugely* bad way round it.
[quoted text clipped - 14 lines]
> At design time I do'nt know all Customer properties. So I cannot create cs
> file containing full-property constructor and thus cannot use subclassing.

To be honest, despite your explanations it's still not at all clear
what you're trying to do. However, it's equally unclear why you're
holding on to this "full-parameter constructor" idea despite it clearly
having issues, when setting properties would appear to be a lot
simpler.

> > No, it doesn't. I don't know exactly what it *does* do (it seems to
> > avoid properties too) but there's no constructor with parameters for it
[quoted text clipped - 11 lines]
> and use reflection to set new entity properties, one-by-one.
> I see no other way.

I've just had a closer look, and it uses the Storage property of the
Column attribute applied to the relevant property, then sets the field
directly (presumably with reflection).

> However in my case this requires re-writing parts of DbLinq driver code.
>
[quoted text clipped - 11 lines]
> dirty hack to fix
> GetProperties() ordering issue seems to be optimal in this case, is'nt it ?

Not if the point is to see whether it's suitable for production use -
using a technique which you know shouldn't be used for production seems
like a bad idea to me.

Using the parameter names is more reasonable, however.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.