C# 在对象模型中定义关系的最佳方法?

C# 在对象模型中定义关系的最佳方法?,c#,database,database-design,object-model,C#,Database,Database Design,Object Model,在构建将类映射到数据库表的对象模型时,如何指定与其他实体的关系 例如: Category ---------------------- CategoryId INT PK Name VARCHAR Description VARCHAR Product ---------------------- ProductId INT PK CategoryId INT FK Name VARCHAR UnitPrice DECIMAL U

在构建将类映射到数据库表的对象模型时,如何指定与其他实体的关系

例如:

Category
----------------------
CategoryId  INT     PK
Name        VARCHAR
Description VARCHAR

Product
----------------------
ProductId   INT     PK
CategoryId  INT     FK
Name        VARCHAR
UnitPrice   DECIMAL
UnitInStock INT


class Category 
{
     public int CategoryId { get; set; }
     public string Name { get; set; }
     public List<Product> Products { get; set; } //for navigation only
}

class Product
{
     public int ProductId { get; set; }
     public string Name { get; set; }
     public decimal UnitPrice { get; set; }
     public int UnitInStock { get; set; }
}

或者两者都有?(一个用于数据库绑定(
int CategoryId
)一个用于导航(
Category
类别


这取决于您试图实现的目标。如果您需要反向导航,请将主类本身添加为变量;但是如果您不需要(或者如果您不希望需要),则可以添加标识符


但是,我认为您应该选择其中一种方法并实现它。如果您尝试同时使用这两种方法,可能会导致问题。例如,假设在某些类中,您已将main类添加为backnavigation属性;那么,如果在某些情况下不需要,您将进行一些不必要的db查询,或者在s中使用null,该怎么办有些情况。

这实际上取决于您在关系方面需要从模型中获得什么。通过在
产品中加入对
类别的任何类型的引用,您在模型级别上创建了一种双向关系。从数据完整性的角度来看,这在DB级别上可能是必要的,但这并不意味着您的模型必须效仿,这样做并不总是有意义的

在我看来,
产品
不应该知道关于
类别
的任何信息,因为它没有必要知道。一个
产品
可以独立存在,而不必与
类别
关联。但是,如果你觉得
产品
应该知道它的
类别
,那么就一定要添加属性

Id属性与导航属性


这同样取决于您的需求。通常使用导航属性更能证明未来,因为
ID
属性将作为该属性的一部分。但是,当您真正需要的只是
ID
时,您可能会增加额外的开销来拉下整个对象。我可以向您展示下面的代码。我可以告诉我们它保持实体之间的关系(数据库中数据实例的对象表示,如消费者、书籍)。它允许在第一次引用相关对象时读取内容

public class EntityHandler<T, V>
        where T : Entity<V>, new()
        where V : DataObject
    {
        private long myDataObjectID;
        private T myEntityObject;
        public delegate Entity<V> GetEntityObject(long oid);

        private GetEntityObject GetEntityObjectFunction;

        private Entity<V> HandledEntity
        {
            set
            {
                if (myEntityObject == null)
                {
                    myEntityObject = (T)value;
                }
            }
            get { return myEntityObject; }
        }

        public EntityHandler(GetEntityObject extCntrGetBO, long oid)
        {
            myDataObjectID = oid;
            GetEntityObjectFunction = extCntrGetBO;
        }

        public T o
        {
            get
            {
                if (myEntityObject == null)
                {
                    myEntityObject = (T)GetEntityObjectFunction(myDataObjectID);
                }
                return myEntityObject;
            }
        }

        public long ID
        {
            get { return myDataObjectID; }
            set
            {
                myDataObjectID = value;
                myEntityObject = null;
            }
        }
    }
公共类EntityHandler
其中T:Entity,new()
其中V:DataObject
{
私有长myDataObjectID;
私有T myEntityObject;
公共委托实体GetEntityObject(长oid);
私有GetEntityObject GetEntityObjectFunction;
私人实体处理实体
{
设置
{
if(myEntityObject==null)
{
myEntityObject=(T)值;
}
}
获取{return myEntityObject;}
}
公共EntityHandler(GetEntityObject ExtCntTargetBO,长oid)
{
myDataObjectID=oid;
GetEntityObjectFunction=ExtCntTargetBo;
}
公共交通
{
得到
{
if(myEntityObject==null)
{
myEntityObject=(T)GetEntityObjectFunction(myDataObjectID);
}
返回myEntityObject;
}
}
公共长ID
{
获取{return myDataObjectID;}
设置
{
myDataObjectID=值;
myEntityObject=null;
}
}
}

您是否在使用类似ORM的实体框架?如果不是,我建议您这样做。“在我看来,产品不应该知道任何关于类别的信息,因为它不需要知道”。如果您正在使用存储库,在将新产品添加到产品存储库时,如何指定它属于哪个类别?@tigrou这是您必须解决的一个实现细节。但是,通常您会将产品添加到该特定类别-您不会添加具有类别的产品。使用当前的setup、 你需要有一个类别,然后才能添加对我来说没有意义的产品。
class Product
{
     //...
     public int CategoryId;
}
class Product
{
     //...
     public int CategoryId;
     public Category Category;
}
public class EntityHandler<T, V>
        where T : Entity<V>, new()
        where V : DataObject
    {
        private long myDataObjectID;
        private T myEntityObject;
        public delegate Entity<V> GetEntityObject(long oid);

        private GetEntityObject GetEntityObjectFunction;

        private Entity<V> HandledEntity
        {
            set
            {
                if (myEntityObject == null)
                {
                    myEntityObject = (T)value;
                }
            }
            get { return myEntityObject; }
        }

        public EntityHandler(GetEntityObject extCntrGetBO, long oid)
        {
            myDataObjectID = oid;
            GetEntityObjectFunction = extCntrGetBO;
        }

        public T o
        {
            get
            {
                if (myEntityObject == null)
                {
                    myEntityObject = (T)GetEntityObjectFunction(myDataObjectID);
                }
                return myEntityObject;
            }
        }

        public long ID
        {
            get { return myDataObjectID; }
            set
            {
                myDataObjectID = value;
                myEntityObject = null;
            }
        }
    }