inherited objects

Topics: Developer Forum, User Forum
Sep 13, 2007 at 3:11 AM
Is it possible to have inherited objects that are based on related tables?

for example:

public abstract class Device : DbObjectModel<Device>
{
public abstract string SerialNumber { get; set; }
}

public abstract class Phone : Device
{
public abstract string Color { get; set; }
}

public abstract class PDA : Device
{
public abstract string Name { get; set; }
}


public static main ()
{
PDA p = new PDA();
p.SerialNumber = 123;
p.Name = "palm classic";
DbEntry.Save(p);
}
Coordinator
Sep 13, 2007 at 5:35 AM
Yes, your code almost works. :) Except the PDA is abstract class, so it can not create by new operator. We can use DynamicObject as following:

PDA p = DynamicObject.NewObject<PDA>();
Please remember that PDA class mapped to the table named "PDA", so I recommanded the following code:

public abstract class Device<T> : DbObjectModel<T>
{
    public abstract string SerialNumber { get; set; }
}
 
public abstract class Phone<T> : Device<T>
{
    public abstract string Color { get; set; }
}
 
public abstract class PDA : Device<PDA>
{
    public abstract string Name { get; set; }
}
 
 
public static main ()
{
    PDA p = PDA.New();
    p.SerialNumber = 123;
    p.Name = "palm classic";
    p.Save();
}
If we want the 3 classes all mapped to table "Device", the DbTableAttribute should be use:

public abstract class Device : DbObjectModel<Device>
{
    public abstract string SerialNumber { get; set; }
}
 
[DbTable("Device")]
public abstract class Phone : Device
{
    public abstract string Color { get; set; }
}
 
[DbTable("Device")]
public abstract class PDA : Device
{
    public abstract string Name { get; set; }
}
And, if we don't want abstract class, we can define the columns as fields:

public class Device : DbObject
{
    public string SerialNumber;
}
 
public class Phone : Device
{
    public string Color;
}
 
public class PDA : Device
{
    public string Name;
}

It all works, but I don't think it's very useful of the inherits chain mode.
Sep 13, 2007 at 8:44 PM
Edited Sep 13, 2007 at 8:45 PM
In your example:


public abstract class Device<T> : DbObjectModel<T>
{
public abstract string SerialNumber { get; set; }
}

public abstract class Phone<T> : Device<T>
{
public abstract string Color { get; set; }
}

public abstract class PDA : Device<PDA>
{
public abstract string Name { get; set; }
}


public static main ()
{
PDA p = PDA.New();
p.SerialNumber = 123;
p.Name = "palm classic";
p.Save();
}


You said that PDA would be saved to the PDA table. Would all of its fields be saved to that table, or would it have one record in Device for device-only fields, and one record in PDA with PDA-only fields? This is what I desire. I want to have one table that will have SerialNumber for all devices, both PDA and Phone, and then also have rows in PDA and Phone tables that are linked to the Device table transparently, so when you do:


PDA p = PDA.New();
p.SerialNumber = 123;
p.Name = "palm classic";
p.Save();


It's actually creating a row in the Device table with serialNumber, and a row in the PDA table with Name, and teh PDA table has a reference to the rowID in teh Devices table, so when you do:

PDA p = PDA.Retrieve("MyPda");

It's actually doing a JOIN between the Device record and the PDA record based upon an internal foreign key reference.

Is this possible?

T
Coordinator
Sep 13, 2007 at 11:15 PM
No, it's not.
In DbEntry, the table only mapped to the name it self.
No JOIN inside except you define "JoinOn" attribute.
So PDA will have SerialNumber,Color and Name in the PDA table.
The define of PDA works same as:

public abstract class PDA : DbObjectModel<PDA>
{
    public abstract string SerialNumber { get; set; }
    public abstract string Color { get; set; }
    public abstract string Name { get; set; }
}
Sep 14, 2007 at 7:41 AM
Edited Sep 14, 2007 at 7:48 AM
Thanks for your answers. I think we can make it work with the type of inheritance it supports.

I tested a simple object and ran into another problem that I've had with another ORM, namely the ability to map between UInt64/UInt32/UInt16 in the object and Int64/Int32/Int16 in the Sql Server DB. When I tried creating an object with type uint in the object and int in the DB, I got an error in the mapping between System.Data.DbType.Uint32 and System.Data.SqlDbType.Int32. Is there any way to customize the db abstraction layer to make sure the UInts get mapped to Ints and back? If so, where would these customizations take place?

Can you suggest how I can make this work? In the past I've had to have signed ints in the private fields, and have public unsigned properties getters and setters in which the cast is done manually for each variable.

Here's my object and DB schema:

DbTable("OrmTest")
public class OrmTest : DbObjectModel<OrmTest>
{
public string Name;
public bool IsEnabled;
AllowNull
public byte[] TlsKey;
public uint Count;
}

CREATE TABLE dbo.OrmTest(
Idbigint IDENTITY(1,1) NOT NULL,
Namenvarchar(50) NULL,
IsEnabledbit NULL,
TlsKeyvarbinary(max) NULL,
Countint NULL,
CONSTRAINT PK_OrmTest PRIMARY KEY CLUSTERED
(
Id ASC
)
Coordinator
Sep 15, 2007 at 2:59 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Sep 18, 2007 at 1:46 PM
Unsigned number support is done. It's not release, you can get the source code first.
Nov 5, 2007 at 2:22 PM
Hi Lifeng,

I'm looking trough the samples trying to figure out how to implement the inheritence as pointed above without any success. Could you please provide me with some sample code for this inheritance? For example how should I implement the classes for the following situation where he have a "parent" table with two "descendent" tables? What should I do to instruct the code that the PK is an FK?

DbTable("Human")
public abstract class Human: DbObjectModel<Human>
{
public abstract int HumanID {get; }
public abstract string Name {get; set;}
}

DbTable("Men")
public abstract class Men:Human
{
public string PreferedSport { get; set; }
}

DbTable("Women")
public abstract class Women:Human
{
public string PreferedPurse { get; set; }
}

Thanks,

Eric.
Coordinator
Nov 6, 2007 at 12:59 AM
Just like I told before, in DbEntry, the object only mapped to the table name of it self.

By inhertis from DbObjectModel, we already have a PK named "Id" and type is long.
To define other kind of PK, please visit Object definition.

For FK, it using relations to implements, please visit Relations.
Feb 4, 2008 at 3:17 AM
When should one use DbObject as the base class, and when should DbObjectModel be used? I started with concrete classes that all inherited from DbObject, but using this model and a similar inheritance tree I only wound up with one table with all of the inherited properties.

Thanks!

James
Coordinator
Feb 17, 2008 at 2:28 AM
I recommend to use DbObjectModel for almost all tables.
The inheritance tree does not shows in code. The class only maps for one table.
The relation should be use the relations to handle:
http://www.codeplex.com/DbEntry/Wiki/View.aspx?title=Relations&referringTitle=Home
Oct 28, 2008 at 11:15 AM
I am working on a WCF service project and use DbEntry.Net as the database layer. When I use DbObjectModel,  I never succeeded in adding service reference from the client project. When I use DbObjectBase, service reference is OK.