Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 用POCO类定义链接的实体_Linq_Entity Framework_Ef Code First - Fatal编程技术网

Linq 用POCO类定义链接的实体

Linq 用POCO类定义链接的实体,linq,entity-framework,ef-code-first,Linq,Entity Framework,Ef Code First,我使用EF代码第一类 我有一个名为请求的实体: public class Request { [Key] public virtual int RequestID { get; set; } ... } 我需要相互链接请求 例如: 如果我们有下面定义的两个链接: RequestID 1链接到RequestID 2 RequestID 1链接到RequestID 3 然后 如果我们询问链接了哪些请求: (A) 对于1:结果是2,3 (B) 对于2:结果是1,3 (C

我使用EF代码第一类

我有一个名为
请求
的实体:

public class Request
{
    [Key]
    public virtual int RequestID { get; set; }
    ...
}
我需要相互链接
请求

例如:

如果我们有下面定义的两个链接:

  • RequestID 1链接到RequestID 2
  • RequestID 1链接到RequestID 3
然后

如果我们询问链接了哪些请求:

  • (A) 对于1:结果是2,3
  • (B) 对于2:结果是1,3
  • (C) 对于3:结果是1,2
解释:

  • 对于(A)项,很容易找到结果,因为链接是“直接的”
  • 对于(B)和(C),这有点复杂,因为链接是通过1的“路径”检索的。我不知道我是否清楚
我的问题:定义链接模型类的最佳方式是什么?之后,如何查询(LINQ)这些模型类以检索如上所示的结果

起初,我认为链接模型类如下:(不知道这是否是个好主意)


以下结构可能正是您所寻找的:

实体

public class Request
{
    [Key]
    public virtual int RequestID { get; set; }
    ...
    // Suppose that "1" is related to "2" and "3"
    // "1" -> "2" (1 is the left side of relationship; 2 is the right side)
    // "1" -> "3" (1 is the left side of relationship; 3 is the right side)

    // For "1" it will return "2" and "3"
    // For "2" it will return nothing
    // For "3" it will return nothing
    public virtual ICollection<RequestLinked> RequestsLinked { get; set; }

    // For "1" it will return nothing
    // For "2" it will return "1"
    // For "3" it will return "1"
    public virtual ICollection<RequestLinked> RequestsLinkedThisRequest { get; set; }
}
公共类请求
{
[关键]
公共虚拟int请求ID{get;set;}
...
//假设“1”与“2”和“3”相关
//“1”->“2”(1是关系的左侧;2是右侧)
//“1”->“3”(1是关系的左侧;3是右侧)
//对于“1”,它将返回“2”和“3”
//对于“2”,它将不返回任何内容
//对于“3”,它将不返回任何内容
公共虚拟ICollection请求链接{get;set;}
//对于“1”,它将不返回任何内容
//对于“2”,它将返回“1”
//对于“3”,它将返回“1”
公共虚拟ICollection请求链接此请求{get;set;}
}
映射

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Request>()
        .HasKey(i => i.RequestID);

    modelBuilder.Entity<RequestLinked>()
        .HasKey(i => new {i.RequestID, i.RequestRelatedID });

    modelBuilder.Entity<Request>()
        .HasMany(i => i.RequestsLinked)
        .WithRequired(i => i.RequestRelated )
        .HasForeignKey(i => i.RequestRelatedID )
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<Request>()
        .HasMany(i => i.RequestsLinkedThisRequest )
        .WithRequired(i => i.Request)
        .HasForeignKey(i => i.RequestID)
        .WillCascadeOnDelete(false);


    base.OnModelCreating(modelBuilder);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasKey(i=>i.RequestID);
modelBuilder.Entity()
.HasKey(i=>new{i.RequestID,i.RequestRelatedID});
modelBuilder.Entity()
.HasMany(i=>i.requests链接)
.WithRequired(i=>i.RequestRelated)
.HasForeignKey(i=>i.RequestRelatedID)
.WillCascadeOnDelete(假);
modelBuilder.Entity()
.HasMany(i=>i.requests链接此请求)
.WithRequired(i=>i.Request)
.HasForeignKey(i=>i.RequestID)
.WillCascadeOnDelete(假);
基于模型创建(modelBuilder);
}
请参阅此链接


希望有帮助

我认为您的模型很好,但问题的本质很复杂,我认为没有有效的LINQ查询来检索路径。因为检索路径需要递归地在请求的左右移动。我认为,您最好使用SQL递归查询。大概是这样的:

WITH cte AS ( 
            SELECT RequestLink.*, cast('(' + cast(RequestId as nvarchar(max)) + ',' 
                     + cast(RequestRelatedId as nvarchar(max))+')' as nvarchar(max)) Path 
              FROM RequestLink 
              WHERE RequestId = 3 OR RequestRelatedId = 3
              UNION ALL 

              SELECT a.*,
                   cast(
                         c.Path + '(' + 
                         cast(a.RequestId as nvarchar(max)) + ',' + 
                         cast(a.RequestRelatedId as nvarchar(max)) + ')' 
                       as nvarchar(max)
                       ) Path 
            FROM RequestLink a JOIN cte c ON 
                  a.RequestId = c.RequestRelatedId 
                  OR c.RequestId = a.RequestRelatedId 
                  OR c.RequestId = a.RequestId 
                  OR c.RequestRelatedId = a.RequestRelatedId 
                where c.Path not like cast(
                         '%(' + 
                         cast(a.RequestId as nvarchar(max)) + ',' + 
                         cast(a.RequestRelatedId as nvarchar(max)) + 
                         ')%' 
                       as nvarchar(max)
                       )

  )
  SELECT DISTINCT id from (
     SELECT distinct RequestId as id FROM cte
     union all 
     SELECT distinct RequestRelatedId as id FROM cte
  ) a
此查询首先查找
id=3
,然后递归地附加具有公共id的其他链接,并为其创建路径。已在路径中的路径行将被丢弃。最后,我们选择
一个
不同的
id的数组
s.
您可以在EF上下文中将此查询用作调用
数据库.SqlQuery(…)
的函数

另一种选择是将所有链接加载到内存并构建一个完整的图,然后使用图算法查找路径。如果链接量较小,则可以使用此选项

另一个选项是将导航属性添加到
请求
类,正如Fabio Luzpost建议的那样,在这种方法中,您可以递归地导航两个导航属性并检索子项,直到达到
n
的深度。其中
n
是引用的数量。
在这种方法中,您必须注意循环依赖关系,这可以通过保存一个遍历的
请求列表来克服。

这种方法需要许多DB往返(需要连接以检索导航属性),因此如果路径深度较大,这可能不是一个选项。

您能给我一些关于您的解决方案的解释吗?无论如何,谢谢你。看看代码里面的注释;这种关系适合你的情况吗?谢谢,我明天会试试,并与你保持联系。在这种情况下,你有两个导航属性。第一个将返回当前对象位于关系左侧的情况。第二个将返回当前对象位于关系右侧的情况。看看这篇文章末尾的链接。这可能有用。
WITH cte AS ( 
            SELECT RequestLink.*, cast('(' + cast(RequestId as nvarchar(max)) + ',' 
                     + cast(RequestRelatedId as nvarchar(max))+')' as nvarchar(max)) Path 
              FROM RequestLink 
              WHERE RequestId = 3 OR RequestRelatedId = 3
              UNION ALL 

              SELECT a.*,
                   cast(
                         c.Path + '(' + 
                         cast(a.RequestId as nvarchar(max)) + ',' + 
                         cast(a.RequestRelatedId as nvarchar(max)) + ')' 
                       as nvarchar(max)
                       ) Path 
            FROM RequestLink a JOIN cte c ON 
                  a.RequestId = c.RequestRelatedId 
                  OR c.RequestId = a.RequestRelatedId 
                  OR c.RequestId = a.RequestId 
                  OR c.RequestRelatedId = a.RequestRelatedId 
                where c.Path not like cast(
                         '%(' + 
                         cast(a.RequestId as nvarchar(max)) + ',' + 
                         cast(a.RequestRelatedId as nvarchar(max)) + 
                         ')%' 
                       as nvarchar(max)
                       )

  )
  SELECT DISTINCT id from (
     SELECT distinct RequestId as id FROM cte
     union all 
     SELECT distinct RequestRelatedId as id FROM cte
  ) a