Table bloat in Linq-SQL

A

Andrus

var db = new MyDb(connString);

causes creation of all objects corresponding to all tables in database.

Database contains 500 tables.
Application accesses only few tables at a time.

Creating large number of objects which are not used is bad design.

How to force Linq-SQL to create table objects only when they are first
accessed ?

Andrus.
 
J

Jon Skeet [C# MVP]

Andrus said:
var db = new MyDb(connString);

causes creation of all objects corresponding to all tables in database.

Database contains 500 tables.
Application accesses only few tables at a time.

Creating large number of objects which are not used is bad design.

How to force Linq-SQL to create table objects only when they are first
accessed ?

You could partition your database into several contexts. Are you sure
this is actually an issue for you though? How much memory are you
seeing being used?
 
A

Andrus

You could partition your database into several contexts. Are you sure
this is actually an issue for you though? How much memory are you
seeing being used?

I'm sorry I was not clear.
The actual issue with that is that loading some of database tables requires
creating and loading additional assemblies at runtime. Creating those
assemblies requires some database access also.

Since all 500 tables are loaded always I'm afraid that creating always all
assemblies for all tables with database acess decreases perfomance a lot.

So I'd prefer to create table objects only when required.

I'm looking for a way to modify database class to implement delayed loading
using table object getters or cache some data in isolated storage or some
other idea.

Andrus.
 
J

Jon Skeet [C# MVP]

Andrus said:
I'm sorry I was not clear.
The actual issue with that is that loading some of database tables requires
creating and loading additional assemblies at runtime. Creating those
assemblies requires some database access also.

Is this due to extra code that you've added to the designer-generated
classes? Could you give us a very simple 2-table example with code?
 
A

Andrus

Is this due to extra code that you've added to the designer-generated

Yes, I'm planning to subclass most of tables for additional table columns
defined in customer site
(btw. I use open source DbLinq pgsqlmetal, not Microsoft sqlmetal).
Could you give us a very simple 2-table example with code?

Designer generated code:

namespace EntityBase {

[Table(Name = "customer")]
public class CustomerBase {
public CustomerBase( string id, string name );
}


[Table(Name = "item")]
public class ItemBase {
public ItemBase ( string idItem, string name, int price );
}
}


In AssemblyResolve event I retrieve additional properties from database and
create wrapper assemblies like:

first assembly:

namespace Entity {

[Table(Name = "customer")]
public class Customer: CustomerBase {

[Column(Name = "address", DbType = "character")]
public string Address {get; set;};

public CustomerBase( string id, string name, string address ):base(id,name)
{
_address=address;
}
}
}

second assembly:


namespace Entity {

[Table(Name = "item")]
public class Item: ItemBase {

[Column(Name = "location", DbType = "character")]
public string Location {get; set;};

public Item: ItemBase ( string id, string name, int price, string
location ): base(id, name, price) {
_location = location;
}
}
}

var mydb= new MyDb(connstring);

causes AssemblyResolve events for all tables in database.


Andrus.
 
F

Frans Bouma [C# MVP]

Andrus said:
I'm sorry I was not clear.
The actual issue with that is that loading some of database tables
requires creating and loading additional assemblies at runtime.
Creating those assemblies requires some database access also.

Since all 500 tables are loaded always I'm afraid that creating
always all assemblies for all tables with database acess decreases
perfomance a lot.

So I'd prefer to create table objects only when required.

I'm looking for a way to modify database class to implement delayed
loading using table object getters or cache some data in isolated
storage or some other idea.

I think this is done to be able to create queries at runtime properly
from the expression trees. (otherwise the context will run into unknown
table references).

Why would you want to create these wrappers at runtime? Because that
way you can't program against them.

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#)
------------------------------------------------------------------------
 
A

Andrus

I think this is done to be able to create queries at runtime properly
from the expression trees. (otherwise the context will run into unknown
table references).

pgsqlmetal generates code:

public readonly MTable<Customer> Customers;

public MyDb(string connStr): base(connStr) {

Customers = new MTable<Customer>(this);
.....

}

Is it reasonable to replace Customer field to delayed instantion property
like

public readonly MTable<Customer> customers;

public readonly MTable<Customer> Customers {
get { if ( customers=null )
customers = new MTable<Customer>(this);
return customers;
}

Why would you want to create these wrappers at runtime? Because that
way you can't program against them.

My application should run in a lot of customer sites.
Customers may have added additional columns to tables in database.
I need to edit those columns in grid.
So I need to retrieve those properties from database also.

Andrus.
 
J

Jon Skeet [C# MVP]

Frans Bouma said:
I think this is done to be able to create queries at runtime properly
from the expression trees. (otherwise the context will run into unknown
table references).

You need to create the context, but the context wouldn't need to
actually instantiate anything else before any queries are executed.

Andrus isn't quite clear, IMO - he's given examples where he's added
extra information to an *entity* but I don't expect any actual entities
to be created until the query is executed. I can see why the referenced
assemblies would probably be loaded, but that's a one-time cost, which
could (for instance) be performed explicitly on another thread during
startup.

The tables themselves are created whenever a DataContext is instiated
(I believe, anyway) but no instances of the entities within them.
 
F

Frans Bouma [C# MVP]

Jon said:
You need to create the context, but the context wouldn't need to
actually instantiate anything else before any queries are executed.

Andrus isn't quite clear, IMO - he's given examples where he's added
extra information to an entity but I don't expect any actual entities
to be created until the query is executed. I can see why the
referenced assemblies would probably be loaded, but that's a one-time
cost, which could (for instance) be performed explicitly on another
thread during startup.

The tables themselves are created whenever a DataContext is instiated
(I believe, anyway) but no instances of the entities within them.

It's a source for a lot of miscommunication I think: does he mean
table in the RDBMS, or Table<T>, the object used to build Linq to Sql
queries with?

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#)
------------------------------------------------------------------------
 
F

Frans Bouma [C# MVP]

Andrus said:
pgsqlmetal generates code:

public readonly MTable<Customer> Customers;

public MyDb(string connStr): base(connStr) {

Customers = new MTable<Customer>(this);
....

}

Is it reasonable to replace Customer field to delayed instantion
property like

public readonly MTable<Customer> customers;

public readonly MTable<Customer> Customers {
get { if ( customers=null )
customers = new MTable<Customer>(this);
return customers;
}

What would that bring you? Your code will completely unmaintainable,
as you can't test if your code will work properly nor can you proof
that your code is correct, as at runtime 'Customer' can be anything.
My application should run in a lot of customer sites.
Customers may have added additional columns to tables in database.
I need to edit those columns in grid.
So I need to retrieve those properties from database also.

Sure, but that's not information you can work with at compile time.
I.o.w.: you'll be forced to write code which solely works with
meta-information gathered at runtime.

Instead of doing it the hard way, i.e. via reflection and what not,
you could use datatables instead. The thing is that using reflection
etc., you're also not working with material that's compile time
checked, so the easier way to do this is by using datatables, which are
by definition untyped and can hold any columns you throw at them.

The 'customer needs to add columns themselves' pattern is one which
pops up once in a while and every time the developers run into the same
pitfalls, by ignoring the obvious: when the customer of your software
needs to add columns at runtime, you can't write code which is compile
time checked: the new fields will never be part of code that was there
when the code was compiled: statically typed languages therefore aren't
really useful for this, OR you have to accept the fact that you can't
use statically typed classes which represent an entity definition at
compile time don't match the entity definition at runtime.

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#)
------------------------------------------------------------------------
 
J

Jon Skeet [C# MVP]

On Nov 12, 9:40 am, "Frans Bouma [C# MVP]"

It's a source for a lot of miscommunication I think: does he mean
table in the RDBMS, or Table<T>, the object used to build Linq to Sql
queries with?

I think he means the Table<T> - on the RDBMS there wouldn't be
anything triggering assemblies being loaded etc (typically, anyway).
But yes, some more clarity would be nice :)

Jon
 
A

Andrus

Frans,
What would that bring you?

I hope that this causes assembly containing Customer class to be loaded only
when customer table is referenced.
Wihtout this database content initialization code creates customer class and
this causes customer and all other extended entity assemblies to be loaded
at application startup always.
Your code will completely unmaintainable,
as you can't test if your code will work properly nor can you proof
that your code is correct, as at runtime 'Customer' can be anything.

Customer is based on CustomerBase class. CustomerBase class has known fields
at design time.
So autocomplete, stong typing, refactoring etc. are available at design
time.
Code is very well maintainable.

Since Customer is based on CustomerBase, runtime can add only user-defined
new properties,
not changing base class.
This allows to make customer-specific customizations easily, e.q bind
customer lists to datagridview.
Sure, but that's not information you can work with at compile time.
I.o.w.: you'll be forced to write code which solely works with
meta-information gathered at runtime.

I can create C# scripts running in customer sites which use those extended
customer properties.

In this case I can use all static language goodies together with basic, well
tested core application.

So I do'nt understand why I cannot use extended properties in customer
sites.
Also using extended properties in business objects is only reasonable way to
add customer specific calculated fields to grids.
Instead of doing it the hard way, i.e. via reflection and what not,
you could use datatables instead. The thing is that using reflection
etc., you're also not working with material that's compile time
checked, so the easier way to do this is by using datatables, which are
by definition untyped and can hold any columns you throw at them.

Extended properies design pattern allows to use strong typing in core
appliction with core
properties and customer specific plugins/scripts running at customer sites.
This allows to use same application with exteneded data and thus provides
huge development cost saving.
Moving to untyped datasets loses all strong typing benefits, I must cast
values from strings and use ugly indexing syntax. Datasets are less scalable
and are not developed by MS anymore.

So I have no idea why you recommend to use untyped datasets.
The 'customer needs to add columns themselves' pattern is one which
pops up once in a while and every time the developers run into the same
pitfalls, by ignoring the obvious: when the customer of your software
needs to add columns at runtime, you can't write code which is compile
time checked: the new fields will never be part of code that was there
when the code was compiled:

My base code which uses CustomerBase properties is checked at application
development time.

Scripts using extended properties are checked at dynamic compile time in
customer sites when compiled against extended customer assemblies.

Customer Plugins can refer to Customer assembly containing customer specific
properties and can be checked at design time.

So I do'nt understand this.
statically typed languages therefore aren't
really useful for this, OR you have to accept the fact that you can't
use statically typed classes which represent an entity definition at
compile time don't match the entity definition at runtime.

Yes, in Python it is possible write exception handler inside entity class
which catches missing property exception and returns propery value
corresponding to database column.
I was surprised that this basics capability is not available in .NET.

I havent seen Python development IDE which has VS 2008 quality. Python does
not have integrate GUI framework. It seems to have less users than .NET.
Implementing dynamic properties in .NET seems to be possible some effort.
So I think that switching to Python or other dynamic language increases
development cost a lot.

I think it is time to bring the power of dynamic properties to static
languages.
..NET assembly format allows to map extended assemblies which contain
properties not present in
design time.

Ideablade DevForce supports it well.
There is special lesson teaching this freely downloadable from IdeBlade
website.

I expect that in future every reasonable ORM supports this. ORMs without
dynamic property support will vanish.

Andrus.
 
A

Andrus

Jon,
I think he means the Table<T> - on the RDBMS there wouldn't be
anything triggering assemblies being loaded etc (typically, anyway).
But yes, some more clarity would be nice :)

I'm sorry I was not clear.

Table<T> object instantion causes assembly containing type T to be loaded.

So my issue is: is it possible and reasonable to change sqlmetal generated
code
so that it does not create tables in Data Context constructor?

Is it possible and reasonable to move table creation to table property
getter by implementing getter like

public readonly MTable<Customer> Customers {
get { if ( customers=null )
customers = new MTable<Customer>(this);
return customers;
}

Will Linq-SQL work well in this case in design and run times ?

Or will only reference to Table<T> in assembly cause assembly containing
type T to be loaded ?

If so I think I will create whole extended properties assembly at runtime
and load it fully. If this causes perfomace decrease I hope I can cache this
extented assembly in isolated storage.

I havent seen any .NET application with uses background assembly loading at
startup like windows logon.

Andrus.
 
J

Jon Skeet [C# MVP]

Andrus said:
I'm sorry I was not clear.

Table<T> object instantion causes assembly containing type T to be loaded.

Right, I can understand that.
So my issue is: is it possible and reasonable to change sqlmetal generated
code so that it does not create tables in Data Context constructor?

It may be possible, but it sounds like a bad idea to me. When you
deviate a long way from standard practice, you tend to run into all
sorts of difficulties and very few people are able to help you out.
That's a general observation, not one about LINQ to SQL in particular.
Is it possible and reasonable to move table creation to table property
getter by implementing getter like

public readonly MTable<Customer> Customers {
get { if ( customers=null )
customers = new MTable<Customer>(this);
return customers;
}

At that point you'd need to know the real details of when the CLR loads
any particular type. It's not something I've ever investigated in
*great* detail, but relying on particular behaviour seems like a bad
idea to me - not because it won't work, but because it'll be very
difficult to maintain.
 
F

Frans Bouma [C# MVP]

Andrus said:
I hope that this causes assembly containing Customer class to be
loaded only when customer table is referenced. Wihtout this database
content initialization code creates customer class and this causes
customer and all other extended entity assemblies to be loaded at
application startup always.

Ok, but take a step back for a minute: these assemblies, they're
created on-site at the client, I pressume? Otherwise you wouldn't be
needing them.

So your code accessing these custom types has to be generic, i.o.w.:
it's very very hard to make that reliable.
Customer is based on CustomerBase class. CustomerBase class has known
fields at design time.
So autocomplete, stong typing, refactoring etc. are available at
design time.
Code is very well maintainable.

No, see below.
Since Customer is based on CustomerBase, runtime can add only
user-defined new properties, not changing base class.
This allows to make customer-specific customizations easily, e.q bind
customer lists to datagridview.

Sure, but you can't access these user defined properties in your code,
at least not in a typed fashion. So IF you want to work with these,
you've to fall back on low-level property descriptor voodoo, which is
IMHO not preferable and definitely not maintainable.

Also, your complete application isn't really testable, because the
stuff added for the client is unknown.
I can create C# scripts running in customer sites which use those
extended customer properties.

In this case I can use all static language goodies together with
basic, well tested core application.

How can you write code off-site which accesses in a typed fashion
properties which are added later on?
So I do'nt understand why I cannot use extended properties in customer
sites.
Also using extended properties in business objects is only reasonable
way to add customer specific calculated fields to grids.

No, there are other ways. The thing is that the properties in the
grids are just a facade. You have to implement ITypedList and from then
on you can return whatever you want in property descriptors to make up
a flat list, which for example isn't a flat list at all.

What you want is to add for example 'DutchAddress' to a Customer class
at the client's site, however you can't access DutchAddress in your own
code, as that's compiled and written and tested without that property
on the Customer class. Sure, at runtime you can have binding perhaps,
but that's about it. Where's your validation logic and above all, where
do you test your validation logic for 'DutchAddress' ?

The typical pattern to implement flexible fields in entities is by
using meta-tables, although it's a sucky approach as well, but it's
better than messing with code you can't test on the client's site.

Meta tables work with a couple of tables, where you define 1:n
relations between the extended entity and the list of properties to add
as well. This can be implemented in your code without a problem and
tested. You can even create a UI to create these fields.

As the properties are really 1:n related objects to your 'customer'
entity, you then create an ITypedList implementation on your list to
bind to a grid. That ITypedList implementation returns the Customer
property descriptors but also creates property descriptors for the 1:n
related extra property objects.

Do a search on google about implementing ITypedList, or search my blog
for the article I wrote about this.
Extended properies design pattern allows to use strong typing in core
appliction with core
properties and customer specific plugins/scripts running at customer
sites. This allows to use same application with exteneded data and
thus provides huge development cost saving.
Moving to untyped datasets loses all strong typing benefits, I must
cast values from strings and use ugly indexing syntax. Datasets are
less scalable and are not developed by MS anymore.

So I have no idea why you recommend to use untyped datasets.

Ah, so you're saying that at your location you can write code which
can deal with property FooBar on 'Customer' while there's no Foobar
property at the moment, which is added later on at the client's site?
WHere is the validation logic for FooBar written, as it's not there
yet? Also at the client's site? And where do you test Foobar and its
validation? Also at the clients site? Or not at all?
Yes, in Python it is possible write exception handler inside entity
class which catches missing property exception and returns propery
value corresponding to database column.
I was surprised that this basics capability is not available in .NET.

IIRC python is a dyn. language and not statically typed. Similar to
Ruby, which is ideal for the project you're working on. C# is a
statically typed language, if you want to add properties to a type at
runtime, you can't, it has to be via subclassing. The thing is that if
you do that, you have to take into account this subclass and its
properties. It's not a real problem per se, UNLESS you need to work
with these extra properties in your ORIGINAL code, because that
original code isn't aware of these extra properties nor the subclass.

(via 'dynamic proxy', you can extend classes at runtime in C#, however
code which isn't aware of the added stuff can't work with that extra
stuff, as it doesn't know it's there at compile time. The code which IS
aware of the extra stuff can of course, but imho in your project that's
not code which does exist.
Ideablade DevForce supports it well.
There is special lesson teaching this freely downloadable from
IdeBlade website.

It's a trick, but it has consequences: the thing isn't adding the
property, dynamic proxy can do that, the thing is the code working with
the added property. If I write a validator for Customer, I can't add to
the validator some code working with properties which are added at
runtime by a subclass, because the compiler doesn't know about these
properties.

THAT's what I meant.

With dynamic proxy (the pattern you follow as well, though you
generate the proxy with a script), there's no end to what you can add
to a class. That's not the point. The point is: can you write provable
code which is correct when you say to your client: "It's done"?

You can only do that if you have in your OWN code tests and compile
time checked code which uses the code added at runtime. You can't do
that in C#, as you can't write code which compiles now against
properties which aren't there yet. You can't write validator,
authorizer and what not code which works with properties added at
runtime as they're not there yet.

Adding properties at runtime using dyn. proxy is maybe half a day of
work, but that's just a small part of the puzzle.
I expect that in future every reasonable ORM supports this. ORMs
without dynamic property support will vanish.

Haha no way. :)

Keywords: provable code.

The one thing which counts is that you can proof your code is correct,
that what you give to your client is working code, that the validation
etc. code works properly. As you can't write validation code up front
against stuff that's not there yet, your code can only be provably
correct if the validation code is written AFTERWARDS, but that's not a
dynamic system.

In the past 5 years we have had a couple of customers who also wanted
to extend the entity classes with properties at runtime. We can do that
for fetching (see:
http://weblogs.asp.net/fbouma/archive/2006/06/09/LLBLGen-Pro-v2.0-with-A
SP.NET-2.0.aspx where I add scalar aggregate fields at runtime to
entities)

but for saving it's not that possible, because where do you put the
validation logic you have to test ? Or better: how do you test code
which has to work with stuff that's not there? ;)

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#)
------------------------------------------------------------------------
 
A

Andrus

Frans,
Ok, but take a step back for a minute: these assemblies, they're
created on-site at the client, I pressume? Otherwise you wouldn't be
needing them.

Yes, they are created on client site.
So your code accessing these custom types has to be generic, i.o.w.:
it's very very hard to make that reliable.

I'm planning to have the following code in my WinForms application to show
customers with extended properties using Linq-SQL:

myDataGridView.DataSource = myDataContext.Customers.ToList();

Why this code is not reliable ?
Sure, but you can't access these user defined properties in your code,
at least not in a typed fashion. So IF you want to work with these,
you've to fall back on low-level property descriptor voodoo, which is
IMHO not preferable and definitely not maintainable.

As I wrote below I'm planning to use dynamically compiled scripts in
customer sites.
Those scripts are compiled in customer site and can use extended properties.
Also, your complete application isn't really testable, because the
stuff added for the client is unknown.

Scipts which are created in customer sites are tested in customer sites with
customer data.
Core application containing core customer properties is testable at my
development site.
How can you write code off-site which accesses in a typed fashion
properties which are added later on?

I can access sql server in client site over internet from my office.
server contains table of scripts. I can add scripts to this table. Scripts
are executed at runtime from
my generic core application. In those scripts I can use extended properties
in typed way like

string dutchAddress = from k in db.Customer select k.DutchAddress where
k.id=1;
No, there are other ways. The thing is that the properties in the
grids are just a facade. You have to implement ITypedList and from then
on you can return whatever you want in property descriptors to make up
a flat list, which for example isn't a flat list at all.

Yes, for binding TypeDescriptor interfaces in System.ComponentModel work
well.
However, I'd prefer to use extended properties in LinQ-SQL queries in
scripts running in customer sites also.

How to use the statement

string dutchAddress = from k in db.Customer select k.DutchAddress where
k.id=1;

with ITypedList ?

As Marc wrote in this newsgroup LinQ-SQL does not support TypeDescriptor at
all.
This is very serious Linq-SQL design flaw.
Sublclassing is only way if I want to use Linq-SQL with custom properties.
What you want is to add for example 'DutchAddress' to a Customer class
at the client's site, however you can't access DutchAddress in your own
code, as that's compiled and written and tested without that property
on the Customer class. Sure, at runtime you can have binding perhaps,
but that's about it. Where's your validation logic and above all, where
do you test your validation logic for 'DutchAddress' ?

I use standard Linq-SQL pattern described in LinQ FAQ.

I add a method

OnDutchAddressChanging(String value)

to customer extension class generated at runtime and generate code to call
this method from DutchAddress property setter.

The typical pattern to implement flexible fields in entities is by
using meta-tables, although it's a sucky approach as well, but it's
better than messing with code you can't test on the client's site.

Meta tables work with a couple of tables, where you define 1:n
relations between the extended entity and the list of properties to add
as well. This can be implemented in your code without a problem and
tested. You can even create a UI to create these fields.

I don't know the business logic required to create and validate DutchAddress
at design time.
So this logic should be injected into application and compiled at run time
anyway, even when using meta tables.

I do'nt know any LinQ-SQL provider for meta tables.
Writing and maintaining my only Linq-SQL provider which supports meta-tables
requires a lot more time than dynamic code generation.
As the properties are really 1:n related objects to your 'customer'
entity, you then create an ITypedList implementation on your list to
bind to a grid. That ITypedList implementation returns the Customer
property descriptors but also creates property descriptors for the 1:n
related extra property objects.
Do a search on google about implementing ITypedList, or search my blog
for the article I wrote about this.

Since ITypedList does nor allow to use LinQ, I cannot use it.
Ah, so you're saying that at your location you can write code which
can deal with property FooBar on 'Customer' while there's no Foobar
property at the moment, which is added later on at the client's site?

From my office I can add FoorBar column to server Customer table.
I can create and save FooBar validation script to script table text column
in server.
WHere is the validation logic for FooBar written, as it's not there
yet?

FooBar validation logic will be written in text field in server database.
Dynamic class compiling injects code from this text field to
OnFooBarChanging() method which is called from FooBar setter.

I use
ALTER TABLE customer ADD COLUMN Foobar CHAR(30)

to add column before script is running so column foobar exisits in
customized database.
Also at the client's site? And where do you test Foobar and its
validation? Also at the clients site? Or not at all?

Yes, scripts are running in customer sites.

Most of the testing is done by customer, this reduces develpemnt cost a lot.
Errors is scripts are written to log file which I can read from server table
and change scripts.
IIRC python is a dyn. language and not statically typed. Similar to
Ruby, which is ideal for the project you're working on.

I do'nt know Ruby.
Shoult I really move to Ruby ? Where to find good ide and report designer
like RDLC format reprot designer for Ruby, those are critical for my project
?
C# is a
statically typed language, if you want to add properties to a type at
runtime, you can't, it has to be via subclassing.

It should be possible to use TypeDescriptor also. Unfortunatley LinQ-SQL
does not support TypeDescriptor define properties.
The thing is that if
you do that, you have to take into account this subclass and its
properties. It's not a real problem per se, UNLESS you need to work
with these extra properties in your ORIGINAL code, because that
original code isn't aware of these extra properties nor the subclass.
(via 'dynamic proxy', you can extend classes at runtime in C#, however
code which isn't aware of the added stuff can't work with that extra
stuff, as it doesn't know it's there at compile time. The code which IS
aware of the extra stuff can of course, but imho in your project that's
not code which does exist.

I work with extra properies using scripts, data binding and report designer.
There are no direct references to those extra properties in my code.
It's a trick, but it has consequences: the thing isn't adding the
property, dynamic proxy can do that, the thing is the code working with
the added property. If I write a validator for Customer, I can't add to
the validator some code working with properties which are added at
runtime by a subclass, because the compiler doesn't know about these
properties.

Ideablade dynamic propery tutorial teaches "property discovery" from UI
code.
With dynamic proxy (the pattern you follow as well, though you
generate the proxy with a script), there's no end to what you can add
to a class. That's not the point. The point is: can you write provable
code which is correct when you say to your client: "It's done"?

I can write application using standard properties and sell it to client
saying "it is done and tested".

If client wants to add new properties and custom business logic I can add
this and test additionally without changing core assemblies.
MyGeneration is sample of this. However MyGeneration *reqires* to use
scripts for code generation by extended properties pattern discussed above
*allows* to use scripts.

Andrus.
 
C

codezilla94

Frans,


Yes, they are created on client site.


I'm planning to have the following code in my WinForms application to show
customers with extended properties using Linq-SQL:

myDataGridView.DataSource = myDataContext.Customers.ToList();

Why this code is not reliable ?


As I wrote below I'm planning to use dynamically compiled scripts in
customer sites.
Those scripts are compiled in customer site and can use extended properties.


Scipts which are created in customer sites are tested in customer sites with
customer data.
Core application containing core customer properties is testable at my
development site.


I can access sql server in client site over internet from my office.
server contains table of scripts. I can add scripts to this table. Scripts
are executed at runtime from
my generic core application. In those scripts I can use extended properties
in typed way like

string dutchAddress = from k in db.Customer select k.DutchAddress where
k.id=1;


Yes, for binding TypeDescriptor interfaces in System.ComponentModel work
well.
However, I'd prefer to use extended properties in LinQ-SQL queries in
scripts running in customer sites also.

How to use the statement

string dutchAddress = from k in db.Customer select k.DutchAddress where
k.id=1;

with ITypedList ?

As Marc wrote in this newsgroup LinQ-SQL does not support TypeDescriptor at
all.
This is very serious Linq-SQL design flaw.
Sublclassing is only way if I want to use Linq-SQL withcustom properties.


I use standard Linq-SQL pattern described in LinQ FAQ.

I add a method

OnDutchAddressChanging(String value)

to customer extension class generated at runtime and generate code to call
this method from DutchAddress property setter.



I don't know the business logic required to create and validate DutchAddress
at design time.
So this logic should be injected into application and compiled at run time
anyway, even when using meta tables.

I do'nt know any LinQ-SQL provider for meta tables.
Writing and maintaining my only Linq-SQL provider which supports meta-tables
requires a lot more time than dynamic code generation.


Since ITypedList does nor allow to use LinQ, I cannot use it.


From my office I can add FoorBar column to server Customer table.
I can create and save FooBar validation script to script table text column
in server.


FooBar validation logic will be written in text field in server database.
Dynamic class compiling injects code from this text field to
OnFooBarChanging() method which is called from FooBar setter.

I use
ALTER TABLE customer ADD COLUMN Foobar CHAR(30)

to add column before script is running so column foobar exisits in
customized database.


Yes, scripts are running in customer sites.

Most of the testing is done by customer, this reduces develpemnt cost a lot.
Errors is scripts are written to log file which I can read from server table
and change scripts.


I do'nt know Ruby.
Shoult I really move to Ruby ? Where to find good ide and report designer
like RDLC format reprot designer for Ruby, those are critical for my project
?


It should be possible to use TypeDescriptor also. Unfortunatley LinQ-SQL
does not support TypeDescriptor define properties.


I work with extra properies using scripts, data binding and report designer.
There are no direct references to those extra properties in my code.


Ideablade dynamic propery tutorial teaches "property discovery" from UI
code.


I can write application using standard properties and sell it to client
saying "it is done and tested".

If client wants to add new properties and custom business logic I can add
this and test additionally without changing core assemblies.
MyGeneration is sample of this. However MyGeneration *reqires* to use
scripts for code generation by extended properties pattern discussed above
*allows* to use scripts.

Andrus.

Here is an example of how you can add properties to an object at
runtime.

http://www.spikesolutions.net/ViewSolution.aspx?ID=080da5ff-9c72-4760-9612-ac5448180a65
 
M

Marc Gravell

Here is an example of how you can add properties to an object
at runtime.

Thanks, but we've already had that conversation - see Andrus's note
above:
Unfortunatley LinQ-SQL does not support TypeDescriptor define properties.

Marc
 
A

Andrus

Unfortunatley LinQ-SQL does not support TypeDescriptor define properties.

Marc,

why do you think it uses TypeDescriptor ?
Maybe it uses dynamic compiling or even direct IL code emit to create
wrapper class ?

In this case it may support LinQ.

Andrus.
 

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