Re: Table bloat in Linq-SQL



Andrus wrote:

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

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.

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.

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.

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.

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.

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.

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.

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.

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?

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.

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



Relevant Pages

  • Re: Best practices accessing data?
    ... I'm thinking making classes for data access. ... do - customer - and orders. ... So I'm thinking: Making a customer class ... separate datasource for each of the functions I wanna point to in the ...
    (microsoft.public.dotnet.general)
  • Re: Passing Business Objects through nTier Web App
    ... My Customer class used to reside in the BLL, but in order for the DAL to ... access the Customer object I needed to move it into another layer which I ... other layer (UIL, BLL, DAL) and I can pass the object between these layers. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: An Abstraction Too Far??
    ... OK Thanks Tim I think that I get it. ... In your example it appears that Customer is ... In this case the load method is used to populate the Customer class, ... data access objects separate from my business objects, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: An Abstraction Too Far??
    ... think about the problem subsequent in the light of the response from ... In your example it appears that Customer is ... In this case the load method is used to populate the Customer class, ... data access objects separate from my business objects, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: WGA Questions
    ... >> LOL! ... So say you change your business name, and your customer puts ... > or any other business is not necessary for product validation. ...
    (microsoft.public.windowsxp.general)