Marc,
I guess at the end of the day your requirement (to add dynamic
properties to the entity) is very hard to reconcile with a
"regular" (fixed) entity model. I'm trying to think of ways out of the
hole, but:
* runtime properties - not supported by ActiveRecord / NHibernate
You also wrote earlier that runtime properties are not supported in Linq, is
this true ?
* subclassing - in theory should work; currently seeing an NHibernate
issue [probably fixable with NHibernate knowledge], but might also be
hard to get the FindAll() etc working unless you do this on the
subclass (perhaps forwarding to a private method on the base-class)
I was unable to make AR FindAll() work with Activerecord/NH. FindAll() is
static method and does not find properties in child class.
I was able to extend linq entity class at runtime using the code below.
In design time I have dummy assembly EntityExtension.dll which contains
using System.Data.Linq.Mapping;
[Table(Name = "Customer")]
public class Customer : EntityBase.CustomerWithStandardProperties {}
This dummy assembly is deleted when application is deployed.
In runtime I use AssemblyResolve to create extended entity using code below.
Is this best solution ?
Andrus.
using System;
using System.Windows.Forms;
using System.Reflection;
using System.CodeDom.Compiler;
class Program {
static void Main(string[] args) {
// delete dummy assembly which is used in design time only.
// this is required to run form VS2008 IDE.
System.IO.File.Delete("EntityExtension.dll");
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Form f = new Form();
DataGridView dgv = new DataGridView();
f.Controls.Add(dgv);
dgv.DataSource = GetData();
Application.Run(f);
}
static Assembly CurrentDomain_AssemblyResolve(object sender,
ResolveEventArgs args) {
if (!args.Name.StartsWith("EntityExtension") ) {
return null;
}
return CreateAssembly();
}
static Assembly CreateAssembly() {
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateInMemory = true;
compilerParameters.ReferencedAssemblies.Add("EntityBase.dll");
// use postgresql linq provider
compilerParameters.ReferencedAssemblies.Add(@"C:\dblinq2007\DbLinq\bin\DbLinq.Pgsql.Prototype.dll");
compilerParameters.ReferencedAssemblies.Add("System.dll");
compilerParameters.ReferencedAssemblies.Add(@"c:\Program Files\Reference
Assemblies\Microsoft\Framework\v3.5\System.Data.Linq.dll");
CompilerResults compilerResults =
provider.CompileAssemblyFromSource(compilerParameters,
@"
using System;
using System.Data.Linq.Mapping;
[Table(Name = ""customer"")]
public class Customer : EntityBase.CustomerWithStandardProperties {
protected string _a_a;
// sample dynamic property
[Column(Name = ""a_a"", DbType = ""character"")]
public string A_a {
get { return _a_a; }
set { _a_a = value; _isModified_ = true; }
}
// sample calculated field
public string xxNimi {
get { return ""Mr "" + Nimi; }
}
public Customer(string id, string a_a):base(id) {
_a_a = a_a;
}}
");
return compilerResults.CompiledAssembly;
}
public object GetData() {
mydb db;
const string connStr = "server=localhost;";
db = newmydb(connStr);
var q = from k in db.Customers select k;
return q.ToList();
}
}
}