By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,186 Members | 1,530 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,186 IT Pros & Developers. It's quick & easy.

LINQ Dynamic Data Model

P: n/a
My problem is this. Our clients create different fields they want to
collect and we allow them build dynamic filters, reports etc...
We run some TSQL to actually create the column and all works very well. We
are now adding a lot more functionality to our filters and could really
benefit from using the LINQ to SQL.

I have experimented with the Dynamic Linq
(http://weblogs.asp.net/scottgu/archi...y-library.aspx)
and it is exactly what we need to let them create their own filters and
such. But when I try to filter on a column that does not exist in the Data
Context I get an error, which is understandable.

They have one table that they can add columns to, so I am going to attempt
to dynamically add the new properties and attributes before running the LINQ
query.

For example, if a client adds a new column called Age of type Int, I want to
add a new property to the object.
So it looks like I need to add a property that looks something like:

[Column(Storage="Age", DbType="Int NOT NULL")]
public int Age { get; set;}

I've been reading different reflection techniques and examples for the past
two days and seems like I'm going around in circles..
Does anyone have any suggestions on how I might accomplish this? Anything
to point me in the right direction would be greatly appreciated.
Jan 15 '08 #1
Share this Question
Share on Google+
15 Replies


P: n/a
I have opposite experience.

I was meaning coding against a known data-context in the c#, not a
base-class - is this still the case? Or are you generating the context
at runtime too? (in which case, coding gets very hard)

But your thoughts are definitely useful here - I suspect you've spent
more time trying to get this scenario working than the rest of us
combined ;-p

Marc
Jan 15 '08 #2

P: n/a
EDBrian wrote:
Should I use the Reflection.Emit to create the derived
type/properties? Like I said in my original post, I've been looking
into reflection and creating a new class dynamically for a couple
days now. Do you have any suggestions or links that might help....
And how are you going to refer to these new properties in your code,
which only appear at runtime?

Dynamic columns at runtime should be solved differently: with a couple
of related tables, one for the values and one for the fields. It is a
bit hard on the querying side, but it's what's possible as the language
used in the program is a statically typed language.

FB
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Jan 16 '08 #3

P: n/a
Should I use the Reflection.Emit to create the derived type/properties?
Like I said in my original post, I've been looking into reflection and
creating a new class dynamically for a couple days now.
Do you have any suggestions or links that might help....
As I wrote there are simpler things than Reflection.Emit:

1. Dynamic Compilation to create assembly. I think I have posted some sample
earlier for Marc in this newsgroup.

2. I just discovered from you link Dynamic Linq library CreateClass()
method, thanks a lot.
Maybe this can be used, if it allows to specify base class and Attributes to
properties, any experiences ?

Sample in doc is very promising:

DynamicProperty[] props = new DynamicProperty[] {
new DynamicProperty("Name", typeof(string)),
new DynamicProperty("Birthday", typeof(DateTime)) };
Type type = DynamicExpression.CreateClass(props);
object obj = Activator.CreateInstance(type);
t.GetProperty("Name").SetValue(obj, "Albert", null);
t.GetProperty("Birthday").SetValue(obj, new DateTime(1879, 3, 14), null);
Console.WriteLine(obj);
I think we must create some class which allows this easily.

Andrus.
Jan 16 '08 #4

P: n/a
Nothing yet. I can't figure out how to specify a base class...then I'm
thinking of using reflection to copy all the properties in my static class
to the new one.
"Andrus" <ko********@hot.eewrote in message
news:ev**************@TK2MSFTNGP05.phx.gbl...
>Should I use the Reflection.Emit to create the derived type/properties?
Like I said in my original post, I've been looking into reflection and
creating a new class dynamically for a couple days now.
Do you have any suggestions or links that might help....

As I wrote there are simpler things than Reflection.Emit:

1. Dynamic Compilation to create assembly. I think I have posted some
sample earlier for Marc in this newsgroup.

2. I just discovered from you link Dynamic Linq library CreateClass()
method, thanks a lot.
Maybe this can be used, if it allows to specify base class and Attributes
to properties, any experiences ?

Sample in doc is very promising:

DynamicProperty[] props = new DynamicProperty[] {
new DynamicProperty("Name", typeof(string)),
new DynamicProperty("Birthday", typeof(DateTime)) };
Type type = DynamicExpression.CreateClass(props);
object obj = Activator.CreateInstance(type);
t.GetProperty("Name").SetValue(obj, "Albert", null);
t.GetProperty("Birthday").SetValue(obj, new DateTime(1879, 3, 14), null);
Console.WriteLine(obj);
I think we must create some class which allows this easily.

Andrus.
Jan 16 '08 #5

P: n/a
EDBrian,

Why not to use use dynamic compilation ?

In design time create wrapper assembly used to satisfy MSBUILD.

At runtime:

1. In start of Main() delete this wrapper assembly

2. In AssemblyResolve event:
2.1 create source code cs file in code for child class, specify base class
from other assembly.
2.2 compile it to assembly
2.3 return this assembly reference in in assemblyresolve event thus
replacing original assembly.

Andrus.

"EDBrian" <pr*****@newsgroups.nospamwrote in message
news:4A**********************************@microsof t.com...
Nothing yet. I can't figure out how to specify a base class...then I'm
thinking of using reflection to copy all the properties in my static class
to the new one.

Jan 16 '08 #6

P: n/a
Is this a good idea even in a web appliation?
We don't have that much traffic, I'm not worried about the possible
execution time, but if I destroy the "currnet type" then create a new type
would it effect other clients if they happen to be accessing the object?

As an experiment I created another partial class (with the same name) and
simply added:

[Column(DbType = "Int")]
public int Age { get; set; }

And I can successfully query my database using the "Age" field. I am trying
to figure out how to add a property to a class dynamically. I am out of
element so it's taking a very long time.
I did find this post:
http://blog.devstone.com/aaron/archi...0/24/1323.aspx
But I think it confused me even more. Can I use the
TypeBuilder/PropertyBuilder on an already existing type or should I go back
to the drawing board?

I even stepped through the System.Linq.Dynamic.ExpressionParser and found
this on line 1336:
MemberInfo[] members = t.FindMembers(MemberTypes.Property |
MemberTypes.Field, flags, Type.FilterNameIgnoreCase, memberName);

So now I'm thinking that maybe I can add another method to accomplish
this...something like:

if(members.length == 0){
//Look for a specific property or method that I can add "Custom Fields"
to..
}

But that is a reach....
"Andrus" <ko********@hot.eewrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
EDBrian,

Why not to use use dynamic compilation ?

In design time create wrapper assembly used to satisfy MSBUILD.

At runtime:

1. In start of Main() delete this wrapper assembly

2. In AssemblyResolve event:
2.1 create source code cs file in code for child class, specify base class
from other assembly.
2.2 compile it to assembly
2.3 return this assembly reference in in assemblyresolve event thus
replacing original assembly.

Andrus.

"EDBrian" <pr*****@newsgroups.nospamwrote in message
news:4A**********************************@microsof t.com...
>Nothing yet. I can't figure out how to specify a base class...then I'm
thinking of using reflection to copy all the properties in my static
class to the new one.

Jan 16 '08 #7

P: n/a
Is this a good idea even in a web appliation?

Yes, this is a good idea.
We don't have that much traffic, I'm not worried about the possible
execution time, but if I destroy the "currnet type" then create a new type
would it effect other clients if they happen to be accessing the object?
You base type and base properties reside is assembly which is not destoryed.
You create wrapper assembly contianing initially no properties.
You delete this wrapper assembly and replace it with new wrapper assembly
containing additional properties defined by web user at run time.
As an experiment I created another partial class (with the same name) and
simply added:

[Column(DbType = "Int")]
public int Age { get; set; }
..NET does not support partial assemblies.
Partial classes require the full source code of whole class to build
assembly.
It is not reasonable to distribute source code with application.
So using partial classes is not possible.
And I can successfully query my database using the "Age" field. I am
trying to figure out how to add a property to a class dynamically. I am
out of element so it's taking a very long time.
I did find this post:
http://blog.devstone.com/aaron/archi...0/24/1323.aspx
But I think it confused me even more. Can I use the
TypeBuilder/PropertyBuilder on an already existing type or should I go
back to the drawing board?
As Marc wrote, Linq does not support properties created using
TypeDescriptor.
So this is not possible.
You can try dynamic compiling example I posted is this newsgroup some time
ago.
If you encounter issues with this I can help you since I use this example
based approach.
I even stepped through the System.Linq.Dynamic.ExpressionParser and found
this on line 1336:
MemberInfo[] members = t.FindMembers(MemberTypes.Property |
MemberTypes.Field, flags, Type.FilterNameIgnoreCase, memberName);

So now I'm thinking that maybe I can add another method to accomplish
this...something like:

if(members.length == 0){
//Look for a specific property or method that I can add "Custom Fields"
to..
}
You can add property by implementing custom TypeDescriptor.
Unfortunately Linq current implementation is not capable to use properties
defined through TypeDesciptor interfase.
Linq current implementation it uses Reflection GetProperties() directly.

Your property would be used only for consumers which use TypeDescriptor
interface like DataGridView or data binding.

Only way is to use dynamic compiling or Reflection.Emit to create new type
in new assembly.

Andrus.
Jan 17 '08 #8

P: n/a
I'm sold...with your suggestion of:
You base type and base properties reside is assembly which is not
destoryed.
You create wrapper assembly contianing initially no properties.
You delete this wrapper assembly and replace it with new wrapper assembly
containing additional properties defined by web user at run time.
I can't find your post from the past...do you happen to have a link to it?
I'm stepping out of my comfort zone here and would love to see an
example/explination to point me in the right direction.

Any pointers or good reads you can help me with?

Jan 17 '08 #9

P: n/a
>You base type and base properties reside is assembly which is not
>destoryed.
You create wrapper assembly contianing initially no properties.
You delete this wrapper assembly and replace it with new wrapper assembly
containing additional properties defined by web user at run time.

I can't find your post from the past...do you happen to have a link to it?
I'm stepping out of my comfort zone here and would love to see an
example/explination to point me in the right direction.

Any pointers or good reads you can help me with?
I can send vs2008 solution to you by e-mail.

Andrus.

Jan 17 '08 #10

P: n/a
I'd appreciate it...

how about...prizeloop at yahoo . com

"Andrus" <ko********@hot.eewrote in message
news:uz****************@TK2MSFTNGP03.phx.gbl...
>>You base type and base properties reside is assembly which is not
destoryed.
You create wrapper assembly contianing initially no properties.
You delete this wrapper assembly and replace it with new wrapper
assembly
containing additional properties defined by web user at run time.

I can't find your post from the past...do you happen to have a link to
it?
I'm stepping out of my comfort zone here and would love to see an
example/explination to point me in the right direction.

Any pointers or good reads you can help me with?

I can send vs2008 solution to you by e-mail.

Andrus.
Jan 17 '08 #11

P: n/a
I'd appreciate it...

I sent it.

Andrus.
Jan 18 '08 #12

P: n/a
Thanks...I haven't received it yet....but I'll keep an eye out.
(prizeloopATyahoo.c0m)

It looks like you are the reflection expert so I've these might be dumb
questions, but here we go.
I can easily create a dynamic class right:
-----------------------------------------
DynamicProperty[] props = new DynamicProperty[]{
new DynamicProperty("Age", typeof(int)),
new DynamicProperty("Birthday", typeof(DateTime))
};
Type typ = DynamicExpression.CreateClass(props);
object obj = Activator.CreateInstance(typ);
-----------------------------------------

And again (just to reiterate) I don't need any compile time checking...I
just want the Dynamic LINQ not to throw an exception.
Is there some way I can do something of this sort (I know this doesn't work,
just trying to get my point across):
-----------------------------------------
Table<ADummyClasstable =
datacontext.GetTable(typeof(Facade.CreateDynamicTy pe)) as
Table<ADummyClass>;
-----------------------------------------

As I'm sure you know the problem is the typeof(Facade.CreateDynamicType)
because "CreateDynamicType" is a property and not a class.
I've tried some quick tests by making the CreateDynamicType a method that
returns a Type and other stupid ideas that just didn't work.

What do you think? Is this something I should pursue, getting the
"typeof(Facade.ReturnDyanmicSomething)"? Or should I work on trying to
re-create the "ADummyClass" at runtime? Again, creating a class wasn't that
hard using the DynamicExpression.Createclass() method, but I am out of my
element trying to delete the "ADummyClass" and creating a new one at
runtime...

Thoughts?

Jan 18 '08 #13

P: n/a
Thanks...I haven't received it yet....but I'll keep an eye out.
(prizeloopATyahoo.c0m)
I sent it a lot of hours ago so you should received it.
I uploaded it to

http://eetasoft.ee/eevalinq.zip
It looks like you are the reflection expert
I'm just learning C# and Linq. I'm not expert in any way.
Is there some way I can do something of this sort (I know this doesn't
work, just trying to get my point across):
-----------------------------------------
Table<ADummyClasstable =
datacontext.GetTable(typeof(Facade.CreateDynamicTy pe)) as
Table<ADummyClass>;
-----------------------------------------
I use DbLinq Generic GetTable<ADummyClassfunction for similar case like

class MyForm<ADummyClass {
....
Table<ADummyClass tbl = datacontext.GetTable<ADummyClass>();
....
}

I think it is possible to create your function GetTable( Type t )
which uses reflection to pass type t to GetTable<ADummyClass>() function.

Thoughts?
MakeGenericType() is nice function.

Andrus.
Jan 18 '08 #14

P: n/a
Typically you create two tables: one for the field definitions and one for the values
for these fields per row.
See also: http://groups.google.com/group/micro...3d69c83f1401c3

Same idea, but keeping the values in one place rather than a separate
table; you still need the field definitions, though.

Marc
Jan 19 '08 #15

P: n/a
So currently I'm thinking that it is not worth to change database structure
and application concepts in my case.
I agree; my xml answer was mainly aimed at what sounds like a green-
field implementation.
However this requires creating new
linq driver which translates custom property operations to xml operations in
this column.
Well, that's the kicker. First - I actually really like the LINQ idea,
but the one thing that *really, really, really* annoys me about the
LINQ /implementation/ is that Expression is bound to a MemberInfo, not
something more abstract. That makes it simply impossible to create an
Expression based on a dynamic PropertyDescriptor; and without an
Expression there is nothing for a provider to work with - regardless
of what that provider is. So without re-writing Expression we will
*never* be able to create a sort etc on such a property.

This is truly disappointing; I know /why/ they did it (since
Reflection.Emit uses MemberInfo etc) - but it would have been just as
easy to allow an *abstract* implementation, and *if* they detect that
it is a reflection implementation then locate the matching MemberInfo,
otherwise just invoke the descriptor. Oh well.

For info, not LINQ - but I have written an ORM-esque "search"
implementation that *can* query / sort etc within an xml column
(provided that the somewhere describes the xpath for the property in
question), but it ain't gonna work with LINQ ever as far as I can
tell.

But : if the use case is to store some additional data against a
record, it will do the job quite nicely, without the complexity of
joining through 2 other tables to get the data.

It all depends on what you want to achieve.

Marc

But
Jan 19 '08 #16

This discussion thread is closed

Replies have been disabled for this discussion.