简体   繁体   English

设计表以避免循环引用

[英]Designing tables to avoid circular reference

Working in one project (Catering theme ) when I was designing the database I didn't take care about some thing , and now Is very hard to avoid some kine of errors(Circular error). 当我设计数据库时,在一个项目(餐饮主题)中工作时,我什么都不在意,现在很难避免一些错误(循环错误)。

Suppose I have following scenario : 假设我有以下情形:

I have Meal object that should be composed from a list of semi-finished products (we will call it Product ) and list of simple Resources . 我有一个应该从半成品列表组成膳食对象(我们称之为产品 )和简单的资源列表。

One Product is composed from a list of Resoruces and list of products . 一种产品资源清单和产品清单组成。 So in real example this will look like this: 因此,在实际示例中,它将如下所示:

Meal : Pizza that contains list of Resoruces ( cheese , dough ) and list of Products : in our case will be just :Sauce. 膳食 :包含Resoruces奶酪面团 )列表和Products列表的Pizza:在我们的情况下将仅是:Sauce。 Sauce will be composed from List of Resources ( salt , Some cheese , tomato Sauce ) and a List of Products (in our case will be just one "Chopped tomatoes with salt") So now I have following classes: 酱将由资源列表( 一些 奶酪番茄 )和产品列表(在我们的情况下只是一个“加盐切碎的西红柿”)组成,所以现在我有以下课程:

public class Resource
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }


    public class ProductToProduct
    {
        public int Id { get; set; }
        public Product MainProduct { get; set; }
        public Product Component { get; set; }
        public double Quantity { get; set; }
    }

    public class ProductToResource
    {
        public int Id { get; set; }
        public Product Product { get; set; }
        public Resource Resource { get; set; }
        public double Quantityt { get; set; }
    }

    public class Meal
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public IList<MealToProduct> MealToProducts { get; set; }
        public IList<MealToResource> MealToResources { get; set; }

    }

    public class MealToResource
    {
        public int Id { get; set; }
        public Meal Meal { get; set; }
        public Resource Resource { get; set; }
        public double Quantity { get; set; }

    }


    public class MealToProduct
    {
        public Meal Meal { get; set; }
        public Product Product { get; set; }
        public double Quantity { get; set; }
    }

    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public IList<ProductToResource> ProdcutToResources { get; set; }
        public IList<ProductToResource> ProductToProducts { get; set; }

    }

My problem is in relation between Product to Product . 我的问题是产品之间的关系。

Suppose I will have Product1, Product2 , Product3 , Product4. 假设我将拥有Product1,Product2,Product3和Product4。

Product 1 will be composed from something and Prodcut2, Product4. 产品1将由某种东西和产品2,产品4组成。

Product2 will be composed from something and Prodcut3. Product2将由东西和Prodcut3组成。

Prodcut 3 will be composed from something and Prodcut4. Prodcut 3将由东西和Prodcut4组成。

Prodcut 4 will be composed from something and Prodcut1 , in this case when I will try to calcualte Cost for Product1 , or Product 4 I will get an Circular error. Prodcut 4将由东西和Prodcut1组成,在这种情况下,当我尝试计算Product1的成本或Product 4时,我将得到一个循环错误。

So my problem is in ProductToProduct table. 所以我的问题是在ProductToProduct表中。 My question is how I must to design tables to avoid this kind of errors . 我的问题是我必须如何设计表以避免这种错误。

I AM VERY SORRY FOR MY EXPLICATION BUT IT IS VERY HARD TO EXPLAIN THIS PROBLEM. 非常抱歉,但很难解释这个问题。 PLEASE ASK ME IF SOMETHING IS UNCLEAR. 如果不清楚,请问我。 THANKS FOR YOUR ATTENTION. 感谢您的关注。

Note:This is not so important for this case but I am working in ASP.Net mvc , orm is Fluent Nhibernate. 注意:对于这种情况,这并不是很重要,但是我正在ASP.Net mvc中工作,orm是Fluent Nhibernate。

Here's an example of a function you could use to detect whether a parent-child relationship exists. 这是一个函数示例,可用于检测是否存在父子关系。 I have assumed that the product relationships are described in a table called ProductLink , which has two foreign keys to Product : ParentProductId and ChildProductId . 我假设在称为ProductLink的表中描述了产品关系,该表具有两个Product外键: ParentProductIdChildProductId

This function uses a recursive query to determine the complete list of products which are children of the product denoted by the argument @ParentProductId , then does a simple test to see whether @ChildProductId appears in that list. 此函数使用递归查询确定由参数@ParentProductId表示的产品子项的完整产品列表,然后进行简单测试以查看@ChildProductId是否出现在该列表中。

create function dbo.ProductRelationshipExists
(
    @ParentProductId int,
    @ChildProductId int
)
returns bit
as
begin
    declare @ChildExists bit = 0;

    with ProductChildCTE as
    (
        -- Base case: Get the parent's direct children.
        select ChildProductId from ProductLink where ParentProductId = @ParentProductId

        -- Recursive case: Get the children's children.
        union all
        select
            ProductLink.ChildProductId
        from
            ProductChildCTE
            inner join ProductLink on ProductChildCTE.ChildProductId = ProductLink.ParentProductId
    )
    select @ChildExists = 1 from ProductChildCTE where ChildProductId = @ChildProductId;

    return @ChildExists;
end

When someone tries to insert a record into ProductLink , you could use a test like this to determine whether the proposed parent and child are already in the table as child and parent, respectively, and disallow the insertion if so. 当某人试图将一条记录插入ProductLink ,您可以使用类似的测试来确定提议的父项和子项是否已经分别以子项和父项的形式存在于表中,如果允许,则不允许插入。

This was just a quick write-up to illustrate one possible approach; 这只是一个简短的文章,以说明一种可能的方法。 I should mention that I don't know how well the performance of this thing will scale as the table gets larger. 我应该提及的是,我不知道随着表的变大,此功能的性能将如何扩展。 Hopefully it will suffice for your case. 希望它能满足您的情况。 If not, let me know how to improve it. 如果没有,请让我知道如何改善。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM