做“要么/或”的好方法实体框架 (SQL Server) 中的关系

发布于 2024-11-06 18:21:53 字数 2085 浏览 0 评论 0原文

假设我有两个实体对象“桌子”和“鸡”。

现在假设我有一个“翅膀”对象,我希望该翅膀与桌子和鸡有 0..1-1 的关系。换句话说,我想要一个可为空的 table.wing 和一个可为空的 Chicken.wing。

有没有一种好方法,使用实体框架 4,使翼对象具有可以与表或鸡关联的限制?

注意:我不想在我的字典中包含 wingedobjects 基类 - 这需要是“有一个”而不是“是一个”。

我的想法是,我无法对引用集合进行独特的限制,所以我必须用类似的东西包装实体属性:

public partial class Wing:
...
  public Table Table
    {
      get { return this.Table; }
      set { 
          //make sure Chicken is null
          this.Table = value;
          }
    }
...
}

这让我觉得很老套而且不太干净,所以我一直在寻找更好的如果不是最好的,则实践解决方案。

编辑:

需要明确的是,我目前在桌子和翅膀之间有 0..1-1 关系,在鸡和翅膀之间有 0..1-1 关系。因此,我可以创建一个 table.wing,然后可以查看 wing.table。我想要的是确保在查询 table.wing.chicken 或 Chicken.wing.table 时始终具有空值。该侧翼必须与一张桌子或一个侧翼关联。

当前行为示例:

响应 @morganppdx 的评论:

给定此实体图:

在此处输入图像描述

以及程序中的以下内容.cs:

class Program
{  
 static void Main(string[] args)
    {
        Model1Container container = new Model1Container();

        Wing chickenwing = new Wing { Shape = "birdlike" };
        Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
        Table table1 = new Table { Style = "Mission", Wing = chickenwing }; // Should throw exception!
        container.AddToChickens(chicken1);
        container.AddToTables(table1);
        container.SaveChanges();

        Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
        Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
        Console.ReadLine(); //wait for input to give us time to read
    }
}

结果控制台将显示:

Table 1's wing has a birdlike shape...Table 1 has Andalusian chicken wings!

这个结果是我希望避免的。当 Chickenwing 与 table1 关联时,它应该抛出异常,因为它已经与 Chicken1 关联,并且不能同时与表和鸡关联。

我很可能错误地建立了关系,因此没有在我想要的地方得到 @morganpdx 声明的异常。

代码位于:https://github.com/mettadore/WingThing

Let's say I have two entity objects "table" and "chicken."

Now let's say, I have a "wing" object, and I want that wing to have a 0..1-1 relationship with table and chicken. In otherwords, I want a nullable table.wing and a nullable chicken.wing.

Is there a good way, using Entity Framework 4, to make the wing object have the restriction that it can either be associated with a table OR a chicken?

Note: I don't want to have a wingedobjects baseclass in my dictionary- this needs to be a "has one" not an "is one."

My thought is that I can't make a unique restraint on the collection of references, so I'll have to wrap the Entity properties with something like:

public partial class Wing:
...
  public Table Table
    {
      get { return this.Table; }
      set { 
          //make sure Chicken is null
          this.Table = value;
          }
    }
...
}

This strikes me as pretty hacky and not too clean, so I was looking for a better, if not best, practices solution.

Edit:

To be clear, I currently have a 0..1-1 relationship between table and wing, and a 0..1-1 relationship between chicken and wing. Thus, I can create a table.wing and I can then look at wing.table. What I want is to ensure that I ALWAYS have a null value if I query table.wing.chicken or chicken.wing.table. The wing must be associated with EITHER one table OR one wing.

Example of current behavoir:

In response to @morganppdx's comment:

Given this Entity Diagram:

enter image description here

And the following in Program.cs:

class Program
{  
 static void Main(string[] args)
    {
        Model1Container container = new Model1Container();

        Wing chickenwing = new Wing { Shape = "birdlike" };
        Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };
        Table table1 = new Table { Style = "Mission", Wing = chickenwing }; // Should throw exception!
        container.AddToChickens(chicken1);
        container.AddToTables(table1);
        container.SaveChanges();

        Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));
        Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));
        Console.ReadLine(); //wait for input to give us time to read
    }
}

The resulting console will show:

Table 1's wing has a birdlike shape...Table 1 has Andalusian chicken wings!

This result is what I wish to avoid. It should throw an exception when chickenwing is associated with table1 because it is already associated with chicken1, and cannot be associated with both a table and with a chicken.

It is quite possible that I am building the relationship incorrectly, and thus not getting @morganpdx's stated exception where I want it.

The code is available at: https://github.com/mettadore/WingThing

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

双手揣兜 2024-11-13 18:21:53

在我的脑海中,我的建议是创建扩展 Wing 对象的子对象,并使用它们代替 Wing 对象:

public class ChickenWing : Wing
{
  public Table Table { get { throw new NoTablesAllowedException; }}
}

public class TableWing: Wing
{
  public Chicken Chicken { get { throw new NoChickensHereException; }}
}

然后您发布的代码将如下所示:

class Program
{          
    static void Main(string[] args)           
    {               
        Model1Container container = new Model1Container();                      
        ChickenWing chickenwing = new ChickenWing { Shape = "birdlike" };
        TableWing tablewing = new TableWing { Shape = "circular" };
        Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };               
        Table table1 = new Table { Style = "Mission", Wing = tablewing };             
        container.AddToChickens(chicken1);               
        container.AddToTables(table1);               
        container.SaveChanges();                      

        Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));               
        Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));               
        Console.ReadLine(); //wait for input to give us time to read           
    }       
} 

迄今为止我还没有做过类似的事情,但我相信这应该可行。本质上,Wing 对象充当描述 ChickenWing 和 TableWing 对象的接口,但这些是用于谨慎目的的谨慎对象。

Off the top of my head, my suggestion would be to create child objects that extend the Wing object, and use those instead of your Wing object:

public class ChickenWing : Wing
{
  public Table Table { get { throw new NoTablesAllowedException; }}
}

public class TableWing: Wing
{
  public Chicken Chicken { get { throw new NoChickensHereException; }}
}

The code you posted would then look like this:

class Program
{          
    static void Main(string[] args)           
    {               
        Model1Container container = new Model1Container();                      
        ChickenWing chickenwing = new ChickenWing { Shape = "birdlike" };
        TableWing tablewing = new TableWing { Shape = "circular" };
        Chicken chicken1 = new Chicken { Breed = "Andalusian", Wing = chickenwing };               
        Table table1 = new Table { Style = "Mission", Wing = tablewing };             
        container.AddToChickens(chicken1);               
        container.AddToTables(table1);               
        container.SaveChanges();                      

        Console.Write(String.Format("Table {0}'s wing has a {1} shape...", table1.Id, table1.Wing.Shape));               
        Console.Write(String.Format("Table {0} has {1} chicken wings!", table1.Id, table1.Wing.Chicken.Breed));               
        Console.ReadLine(); //wait for input to give us time to read           
    }       
} 

I have not done anything like this to date, but I believe this should work. Essentially the Wing object acts as an Interface to describe the ChickenWing and TableWing objects, but those are discreet objects used for discreet purposes.

千年*琉璃梦 2024-11-13 18:21:53

看看你的模型,我认为你可以简单地将表和翼 ID 设置为具有不同种子和增量 2 的 IDENTITY - 一个只有偶数,第二个只有奇数 ID,在这种情况下,永远不会有与两者相关的翼。

要点是,EF 中的一对一关系始终建立在主键上,因此 wing 必须具有表或鸡的主键,并且在定义独占序列时,永远不会发生 wing 可以同时拥有表和鸡的情况。

Looking on your model I think you can simply make Table and Wing Ids as IDENTITY with different seed and increment 2 - one will have only even and second only odd Ids and in such case there will never be wing which will be related to both.

The point is that one-to-one relation in EF is always built on primary keys so wing must have primary key of either table or chicken and when defining exclusive sequences it will never happen that wing can have both table an chicken.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文