- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
EntityFactory Classes for Linq
Joined: 05-May-2004
Hi,
How do we provide EntityFactory class in Linq query provider?
I have added the following property in the generated code! File: FactoryClasses\EntityFactories.cs Class: EntityFactoryFactory
public static Dictionary<Type, IEntityFactory2> FactoryPerType
{
get { return _factoryPerType; }
}
When an application starts, it needs to provide new factory classes as follow:
layers.data.FactoryClasses.EntityFactoryFactory.FactoryPerType[typeof(layers.data.EntityClasses.ShpProductEntity)] = new layers.business.FactoryClasses.ShpProductEntityFactory();
Above change creates business layer entity object, instead of data layer entity. Is it any alternative way to achieve this? Would you please give some feedback?
Regards.
Currently there's no way to specify the factory as is: the collection into which the entities are fetched is created on the fly.
Could you elaborate a bit where you want to use a different factory and why? I guess the factories you want to use are producing subtypes of the entity classes already available?
I.o.w.: could you give an example of such a modified factory and where you want to use it?
Joined: 05-May-2004
Hi Otis,
Currently, I have "data" layer as LLBL generated code, and "business" layer inherited entity and collection classes, as follow:
Business layer entity class is defined as:
// business layer entity class
public class ProductEntity : data.EntityClasses.ProductEntity
{
// CTor and business layer implementation (methods/properties..)
}
Business layer collection class is defined as:
// business layer collection class
public class ProductCollection : EntityCollection<business.EntityClasses.ProductEntity>
{
// CTor
public ProductCollection() : base(new business.FactoryClasses.ProductEntityFactory()) { }
// business layer implementation (methods/properties..)
}
Please note that 'ProductEntityFactory' object has been supplied to collection classes, so ProductCollection contains business layer entities, instead of data layer entities.
Business layer Factory is defined as:
public partial class ProductEntityFactory : data.FactoryClasses.ProductEntityFactory
{
public ProductEntityFactory() : base() { }
public override IEntity2 Create()
{
IEntity2 toReturn = new business.EntityClasses.ProductEntity();
return toReturn;
}
public override IEntity2 Create(IEntityFields2 fields)
{
IEntity2 toReturn = new business.EntityClasses.ProductEntity(fields);
return toReturn;
}
}
Instead of writing a partial classes or changing template files, the above code gives me more flexibility to add/update entity or collection functionality.
In v2.6, LLBLGen has '_factoryPerType' static variable, which holds entity factory for each type. If this varibale is available as public property, we could provide our own factory objects - when application starts... as follow:
layers.data.FactoryClasses.EntityFactoryFactory.FactoryPerType[typeof(layers.data.EntityClasses.ProductEntity)] = new layers.business.FactoryClasses.ProductEntityFactory();
Also, LLBLGen v2.6 has to create an instance through this factory methods only.
Currently, LLBLGen uses 'EntityFactoryFactory' and 'GeneralEntityFactory' classes to create an instance of factory class, and they are static methods.. so we could not override these classes. Can it be changed?
Regards.
Developer wrote:
Hi Otis,
Currently, I have "data" layer as LLBL generated code, and "business" layer inherited entity and collection classes, as follow:
Business layer entity class is defined as:
// business layer entity class public class ProductEntity : data.EntityClasses.ProductEntity { // CTor and business layer implementation (methods/properties..) }
Business layer collection class is defined as:
// business layer collection class public class ProductCollection : EntityCollection<business.EntityClasses.ProductEntity> { // CTor public ProductCollection() : base(new business.FactoryClasses.ProductEntityFactory()) { } // business layer implementation (methods/properties..) }
Please note that 'ProductEntityFactory' object has been supplied to collection classes, so ProductCollection contains business layer entities, instead of data layer entities.
Hmm. Aren't you creating parallel hierarchies now? (Customer - Order and also BusinessCustomer - BusinessOrder)
I mean, say you have a SupplierEntity which has a 1:n relation with Product. In the generated code it will have a Products property which is an EntityCollection<ProductEntity>. However the Business component derived from SupplierEntity, does that one have a Products property which returns a ProductsCollection instead?
What you're doing sounds like what's being done in the 2-class scenario for Adapter, with the 'My' entity stuff.
Business layer Factory is defined as:
public partial class ProductEntityFactory : data.FactoryClasses.ProductEntityFactory { public ProductEntityFactory() : base() { } public override IEntity2 Create() { IEntity2 toReturn = new business.EntityClasses.ProductEntity(); return toReturn; } public override IEntity2 Create(IEntityFields2 fields) { IEntity2 toReturn = new business.EntityClasses.ProductEntity(fields); return toReturn; } }
Instead of writing a partial classes or changing template files, the above code gives me more flexibility to add/update entity or collection functionality.
Ok, though it also causes parallel hierarchies, which cause other problems. Be aware of that. (like confusion among which collection to use: the base entity one or the business class one)
In v2.6, LLBLGen has '_factoryPerType' static variable, which holds entity factory for each type. If this varibale is available as public property, we could provide our own factory objects - when application starts... as follow:
layers.data.FactoryClasses.EntityFactoryFactory.FactoryPerType[typeof(layers.data.EntityClasses.ProductEntity)] = new layers.business.FactoryClasses.ProductEntityFactory();
Also, LLBLGen v2.6 has to create an instance through this factory methods only.
Currently, LLBLGen uses 'EntityFactoryFactory' and 'GeneralEntityFactory' classes to create an instance of factory class, and they are static methods.. so we could not override these classes. Can it be changed? Regards.
It's a static set of methods because it builds the factory cache before any code runs the factories, so there doesn't have to be a lock on the cache. If you want to manipulate that cache, it will need a lock and that degrades performance significantly, as it's now multi-threaded aware, and with a lock a single thread can obtain a factory instance.
The cache is used to limit memory usage: every factory instance eats some memory and having a lot of entities in memory with each having their own factory instances of the same factory it's a bit overkill.
One way around this is by using a modified template, which you bind to the same templateid in your own templatebindings file, which you give higher precendence over the existing one (so yours is picked). This is straight forward and IMHO the best way to do this. The template to change is rather empty, so I don't expect many (if any) bugfixes in this template.
You can also use inheritance for this and a modified LinqMetaData template. You can create a new EntityFactoryFactory and a derived class of the ElementCreator for this. See the difference between derivedEntityFactoriesAdapter.template and entityFactoriesAdapter.template and (in .NET 3.5/C# template folder) derivedEntityLinqMetaDataAdapter.template and linqMetaDataAdapter.template
(use a diff tool like windiff))
The modified LinqMetaData class is required to pass an instance of the derived class of ElementCreator to the DataSource2<T> instances instead of the normal one, so the linq provider will end up in your own factoryfactory