2015-10-25 58 views
0

看起來這個問題在我之前會遇到,但我在網上找不到太多幫助可能是因爲我不知道要搜索什麼。EF和Web API 2多次往返數據庫以填充對象模型

我的問題簡而言之就是我有一個數據庫表。該表有5個鍵給其他表。

然後我有一個模型來表示EF中的這個表。當然,這個表示db表的對象具有List<T>屬性,它們是db中外鍵的表示。這似乎不像EF模型那樣具有這種表格表示,而且還具有其他模型的特性。

我遇到的問題是,調用存儲過程來填充主模型會強制其他調用db來填充相關的List<T>模型。

我期望通過消除多次調用來提高性能。

我唯一想到的就是修改存儲過程以返回多個記錄集並將每個List<T>屬性與其對應的記錄集進行匹配。

我的消毒結構是這樣的。

DB:

sql_Id   Int   PK 
sql_Status  Int   FK 
sql_Reason  Int   FK 
sql_GuestId  Int 
sql_Name   varchar 
sql_Created  DateTime 
sql_Original  Int   FK 

EF:

public class OrderHeader : ClassBase 
{ 
    public OrderHeader() 
    { 
     TaskCodeAssignments = new List<OrderHeaderTaskCodeAssignment>(); 
     StatusReasonCode = new OrderHeaderStatusReasonCode(); 
     StatusCode = new OrderHeaderStatusCode(); 
     Links = new OrderHeaderLinks(); 
    } 

    public int OrderHeaderID { get; set; } 
    public short OrderHeaderStatusCodeID { get; set; } 
    public short? OrderHeaderStatusReasonCodeID { get; set; } 
    public short? OriginatingApplicationId { get; set; } 
    public string CustomerFirstName { get; set; } 
    public string CustomerLastName { get; set; } 
    public OrderHeaderStatusCode StatusCode { get; set; } 
    public OrderHeaderStatusReasonCode StatusReasonCode { get; set; } 
    public CustomerStatusCode CustomerStatusCode { get; set; } 
    public ICollection<OrderHeaderTaskCodeAssignment> TaskCodeAssignments { get; set; } 
} 

public class OrderHeaderStatusCode 
{ 
    public OrderHeaderStatusCode() 
    { 
     OrderHeaderStatusReasonCodes = new List<OrderHeaderStatusReasonCode>(); 
    } 

    public ICollection<OrderHeaderStatusReasonCode> OrderHeaderStatusReasonCodes { get; set; } 
    public virtual ICollection<OrderHeader> OrderHeader { get; set; } 
} 

OrderHeaderStatusReasonCode其他自定義類型在設計上非常相似,所以我離開了爲簡潔。

C#的Web API

public async Task<IHttpActionResult>GetOrdersHistory([FromUri]GetOrderRequestParameters orderParams) 
{ 
    ....removed for brevity.... 

    var query = await TheOrderRepository.GetOrderHistory(getOrder); 

} 

訂單倉庫:

public async Task<IQueryable<OrderHeader>> GetOrderHistory(GetOrderParameters orderParams) 
{ 
    // this is the call to stored procedure that I would modify to return multiple recordsets 
    var storedProcedure = StoredProcedure.Name.MyStoredProc.ToString(); 

    var ordersHistory = await dbctx.Database.SqlQuery<OrderHeader>(...), storedProcParam).ToListAsync(); 

    // now I jump off to fill in the other properties and their data has to come from the db 
    await GetOrdersData(ordersHistory, orderParams.Include); 
} 

private async Task GetOrdersData(List<OrderHeader> ordersHistory) 
{ 
    if (ordersHistory != null) 
    { 
    await LoadOrderStatusCodeForList(ordersHistory); 
    await LoadOrderStatusReasonCodeForList(ordersHistory); 
    await LoadCustomerStatusCodeForList(ordersHistory); 
    await LoadOrderHeaderTaskCodeAssignmentsForList(ordersHistory); 
    await LoadOrderHeaderTaskCodeForList(ordersHistory); 
    } 
} 

再次大多數等待着的是相似的,所以我只是去給一個的例子...

private async Task LoadOrderStatusCodeForList() 
{ 
    ....snipped for brevity... 
    await LoadOrderStatusCode(order.OrderHeaderStatusCodeID)); 
} 

private async Task<OrderHeaderStatusCode> LoadOrderStatusCode(short orderHeaderStatusCodeId) 
{ 
    ....snipped brevity.... 
    var storedProcedure = StoredProcedure.Name.MySprocStatusCode.ToString(); 

    return await _dbctx.Database.SqlQuery<OrderHeaderStatusCode>(...), ...).FirstOrDefaultAsync(); 
} 

編輯

癥結在於此。 OrderHeader具有自定義類型的屬性,基本上這些自定義類型具有必須填充的List<T>。我目前的設計是這樣的,我反覆擊中數據庫來填充這些自定義類型列表屬性。

有沒有辦法讓一次去分貝獲取我所有的信息。如前所述,我能想到的唯一方法是修改存儲過程以返回多個記錄集,然後將其匹配。

順便說一句,這個架構可能是缺陷......在這種情況下,教育我如何正確地填充這樣的複雜對象。

TIA

+0

嘿人,sozs方式很多信息。哪一個是來自控制器的返回對象。我建議你在某處顯示一個ViewModel/ReturnObject,這樣我可以確定你想要的信息。 – Seabizkit

+0

請參閱我對OP的編輯。 – GPGVM

+0

沒有我在哪裏看到OrderModel,如果你包括這我可能能夠建議。 – Seabizkit

回答

2

根本問題是存儲過程不可組合。在SQL中,不能使用任何東西(數據庫表或其他存儲過程)加入存儲過程調用。所以EF也做不到這一點。

如果您想從數據庫中獲取已加載集合的數據,通常您必須使用Include s。 EF會將其轉換爲適當的join,並找出如何從一個大的結果集加載實體及其集合。但是,如前所述,這裏的加入是不行的。

有一種方法可以加載multiple result sets from one stored procedure。海事組織是非常混亂和非常程序化。如果您想繼續使用存儲過程,我會像現在一樣繼續單獨加載數據。其他人可能會建議您可以通過延遲加載來加載其他數據。不幸的是,這是not as straightforward as it should beSqlQuery

另一種選擇當然是開始使用常規DbSet s(與Include s),但我不能判斷這對你是否可行。