.net - C# abstract base class for common columns in LINQ -
this have far
using system; using system.collections.generic; using system.data.linq; using system.data.linq.mapping; using system.linq; using system.text; namespace firelight.business { public interface ibaseentity<k> { k id { get; } } /// <summary> /// base business database connection object, primary key int /// </summary> /// <typeparam name="t">table name</typeparam> public abstract class baseentity<t> : baseentity<t, guid> t : class, ibaseentity<guid> { } /// <summary> /// base business database connection object /// </summary> /// <typeparam name="t">table name</typeparam> /// <typeparam name="k">primary key type</typeparam> public abstract class baseentity<t,k> : ibaseentity<k> t : class, ibaseentity<k> { // avoids having declare ibaseconnection @ partial class level [column(name = "id", canbenull = false, isprimarykey = true, isdbgenerated = true)] public k id { get; set; } // { return default(k); } public static table<t> table { { return linqutil.context.gettable<t>(); } } public static t searchbyid(k id) { return table.single<t>(t => t.id.equals(id)); } public static void deletebyid(k id) { table.deleteonsubmit(searchbyid(id)); linqutil.context.submitchanges(); } } }
my problem mapping doesn't work:
data member 'system.guid [or system.int32] id' of type 'x' not part of mapping type 'x'. member above root of inheritance hierarchy?
before trying map attributes, got instead:
could not find key member 'id' of key 'id' on type 'x'. key may wrong or field or property on 'x' has changed names.
i tried changing k guid , works, why? don't see how generic-typing issue here
i'm not entirely sure needed interface either, don't remember why added it.
so, question be: how can make class work? want can access commonly named pk (id), has type k [which guid or int32], , refactor basic functions select , delete id
thanks!
edit:
this works
using system; using system.collections.generic; using system.data.linq; using system.linq; namespace firelight.business { public interface ibaseentity<k> { k id { get; set; } } /// <summary> /// base business database connection object /// </summary> /// <typeparam name="t">table name</typeparam> public abstract class baseentity<t> : ibaseentity<guid> t : class, ibaseentity<guid> { // avoids having declare ibaseconnection @ partial class level public guid id { get; set; } public static table<t> table { { return linqutil.context.gettable<t>(); } } public static t searchbyid(guid id) { return table.single<t>(t => t.id.equals(id)); } public static void deletebyid(guid id) { table.deleteonsubmit(searchbyid(id)); linqutil.context.submitchanges(); } } }
what want same, replacing guid k , making class baseentity (so can use same class int32 , guid pks
what seeking not work linq sql. use inheritance linq sql, have make use of [inheritancemapping] attribute on base class. let's have base class called vehicle , sub-class called motorcycle:
[inheritancemapping(type = typeof(motorcycle), isdefault = true, code = 1)] [table] public class vehicle { [column] pubic string make { get; set; } [column] pubic string model { get; set; } [column(isdiscriminator = true, name="vehicletypeid")] public vehicletype vehicletype { get; set; } } public class motorcycle : vehicle { // implementation here }
in order make inheritance work in linq sql, have apply [inheritancemapping] base class and have have discriminator column (e.g., vehicletype in above example). notice code in inheritancemapping "1" - means if vehicletype database "1" it'll create motorcycle sub-class. apply 1 [inheritancemapping] attribute on base class each sub-class you're supporting.
from purist standpoint, violation of oo because base class knows it's sub-classes. bit of weirdness typically puts people off little how linq sql implements inheritance. there have it.
update works:
public abstract class baseentity<t, k> : ibaseentity<k> t : class, ibaseentity<k> { public abstract k id { get; set; } public static table<t> table { { return context.gettable<t>(); } } public static t searchbyid(k id) { return table.single<t>(t => t.id.equals(id)); } public static void deletebyid(k id) { table.deleteonsubmit(searchbyid(id)); context.submitchanges(); } }
notice difference don't have [column] attribute on id property. notice made abstract. implementing class looks this:
[table(name = "dbo.contacts")] public class contact : baseentity<contact, int> { [column] public override int id { get; set; } [column] public string firstname { get; set; } [column] public string lastname { get; set; } }
notice id property in class does have [column] attribute , i'm overriding abstract propety. verified works.
having said that, there couple of reasons why question current design. first you've got data access methods part of entity , many people (including myself) consider violation of separation of concerns. introduce repository pattern here , have repository each entity - make repository generic based on type , key. other thing weird above approach baseentity has id property , sub-class (in example contact class) has property of id (to make linq sql happy). had make id property in base class abstract , override in implementor. violates dry because i'll have each entity. thing result of hoops have jump through make linq sql happy. will work! :)
Comments
Post a Comment