【问题标题】:How to retrieve a tree of objects from a stored procedure?如何从存储过程中检索对象树?
【发布时间】:2018-02-07 19:07:04
【问题描述】:

我想在包含一些聚合的存储过程中进行计算,以减少发送回调用者的数据量。给定结构:

CREATE TABLE Parent
(
    ParentID int NOT NULL PRIMARY KEY,
    A1 int NOT NULL
)

CREATE TABLE Child
(
    ChildID int NOT NULL PRIMARY KEY,
    ParentID int NOT NULL,
    Expected int NOT NULL,
    CONSTRAINT FK_Child_Parent FOREIGN KEY (ParentID) REFERENCES Parent (ParentID)
)

CREATE TABLE Grandchild
(
    GrandchildID int NOT NULL PRIMARY KEY,
    ChildID int NOT NULL,
    Actual int NOT NULL,
    CONSTRAINT FK_Grandchild_Child FOREIGN KEY (ChildID) REFERENCES Child (ChildID)
)

和存储过程

CREATE PROC testCounts AS
WITH TotalActual AS
(
    SELECT ChildID, SUM(Actual) AS Actual
    FROM Grandchild
    GROUP BY ChildID
)
SELECT ParentID, A1, ChildID, Expected - SUM(Actual) AS Variance
FROM Parent
INNER JOIN Child ON Parent.ParentID = Child.ParentID
INNER JOIN TotalActual ON Child.ChildID = TotalActual.ChildID

我想做的是创建一个类型为Parent 的对象树,其中包含许多ChildVariance 对象。 Entity Framework 能做到这一点吗?

到目前为止我已经定义了:

public class Parent
{
    public Parent()
    {
        ChildVariances = new HashSet<ChildVariance>();
    }

    [Key]
    public int ParentID { get; set; }
    public int A1 { get; set; }
    public virtual ICollection<ChildVariance> ChildVariances { get; set; }
}

public class ChildVariance
{
    [Key]
    public int ChildID { get; set; }

    public int Variance { get; set; }
    public virtual Parent Parent { get; set; }
}

// In my dbContext
public virtual DbSet<Parent> Parents { get; set; }    

override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Parent>
        .HasMany(e => e.ChildVariances)
        .WithRequired(e => e.Parent)
        .HasForeignKey(e => e.ParentID);
}

// In an access method

var results = Parents.SqlQuery("testCounts");

检查results,我得到父行数乘以子行数。 Parent 对象的 Childs 集合中没有条目。

这样做,我得到了代理对象。也就是说,调试器将类名显示为{System.Data.Entity.DynamicProxies.Parent_C553E08E8B955294BB6673459018EE9B5A7FCB3DF260DEC0B7A10621F4560409}。如果我改为创建Parent 和ChildVariance 类sealed,我没有得到代理对象,但它仍然不起作用。

Entity Framework 真的可以通过这种方式从单个结果集中构造对象树吗?如果是这样,我该如何配置?

【问题讨论】:

    标签: sql-server entity-framework-6 ef-code-first


    【解决方案1】:

    这并不能完全回答问题,但我能够通过使用视图而不是存储过程来解决我的实际问题。我不需要多个查询步骤,只需要一个查询。

    CREATE VIEW ChildVariance AS
    WITH TotalActual AS
    (
        SELECT ChildID, SUM(Actual) AS Actual
        FROM Grandchild
        GROUP BY ChildID
    )
    SELECT ParentID, ChildID, Expected, Expected - SUM(Actual) AS Variance
    FROM Child
    INNER JOIN TotalActual ON Child.ChildID = TotalActual.ChildID
    

    然后我可以将ChildVariance 映射为一张桌子:

    public class ChildVariance
    {
        [Key]
        public int ChildID { get; set; }
    
        public int ParentID { get; set; }
    
        public int Expected { get; set; }
        public int Variance { get; set; }
        public virtual Parent Parent;
    }
    

    然后我只需访问Parent.ChildVariances 导航属性来加载数据。要在同一批次中检索它们,我只需将 .Include("ChildVariances") 添加到查询中即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-09
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多