2013-07-25 52 views
3

我在将通过存储过程查询的搜索结果映射到我的EF实体时遇到了一些麻烦。我正在使用数据库第一种方法。将存储过程结果映射到实体框架中的实体5

我可以很容易地使用DbContext.Database.SqlQuery<T>检索简单的实体,只要我的存储过程返回适当的列名称,这个工作并没有问题。然而我的问题是我需要加载相关的实体以及搜索结果。

这就是我的工作:从DbSet<Product>获取数据时

// Product.cs 
public class Product 
{ 
    public int ProductId { get; set; } 
    public int CategoryId { get; set; } 
    public int BrandId { get; set; } 

    public virtual Category Category { get; set; } 
    public virtual Brand Brand { get; set; } 
} 

// Category.cs 
public class Category { 
    public int CategoryId { get; set; } 
    ... 
    more properties 
} 

// Brand.cs 
public class Brand { 
    public int BrandId { get; set; } 
    ... 
    more properties 
} 

一切的伟大工程,导航性能变懒加载预期。

会有一种方式从存储过程中提取所有需要的数据:我的相关实体将被正确填充(即,是否需要以某种特定方式命名我的列)?

我也试验过第二种方法,在这里我简单地从存储过程中拉出List<int>,ProductId,然后使用Linq查询再次访问数据库以拉取实体。

List<int> results = unitOfWork.SqlQuery<int>(
    @"EXECUTE dbo.SomeStoredProcedure @Keyword", 
    new SqlParameter("Keyword", keyword) 
).ToList(); 

List<Product> products = unitOfWork.ProductRepository.Get(
    filter: q => results.Contains(q.ProductId) 
).ToList(); 

这种方法出现了两个问题:两次到数据库和某处丢失命令。我可以忍受的第一个问题,这是一个低流量的应用程序,我并不担心额外的数据库之旅。

第二个是一个更大的问题,虽然。基于存储过程中的某个搜索值排序,结果将按初始查询中的正确顺序进行提取。然后,这个顺序在第二个查询中丢失,留给我一个随机排列的结果集,并且没有办法(我可以看到)将其排序。

任何想法?

+0

您是否曾尝试导入存储过程作为EDMX中的函数?您可以设置返回类型并将存储过程列映射到返回类型属性 – James

+0

@James我没有。我正在使用POCO,并且在我的项目中没有.edmx文件。我可以创建.edmx并只映射存储过程吗? – dom

+0

你可以,如果你这样做,你可以使用它来代替你的'DbContext',虽然它做了同样的事情,并增加了功能。 – James

回答

0

我无法使用.edmx映射工作,所以我最终坚持使用第二种方法,并使用一种非常黑客的方式让我的结果按照他们应该的方式排序。

我拉我的实体有两个查询,在原来的问题(第一个列表是按照正确的顺序)中提到:

public class SearchViewModel : BaseViewModel 
{ 
    public SearchViewModel() 
    { 
     this.Results = new List<int>(); 
     this.Products = new List<Product>(); 
    } 

    public string Keyword { get; set; } 
    public List<int> Results { get; set; } 
    public List<Product> Products { get; set; } 
} 

List<int> results = unitOfWork.SqlQuery<int>(
    @"EXECUTE dbo.SomeStoredProcedure @Keyword", 
    new SqlParameter("Keyword", keyword) 
).ToList(); 

List<Product> products = unitOfWork.ProductRepository.Get(
    filter: q => results.Contains(q.ProductId) 
).ToList(); 

我使用视图模型两个列表传递到我的观点

然后在视图级别而不是循环List<Product>,我遍历结果列表。

<ul class="products medium"> 
    @foreach(int productId in Model.Results){ 
     var product = Model.Products.FirstOrDefault(p => p.ProductId == productId); 
     <li> 
      ... 
      display content 
     </li> 
    } 
</ul> 

感觉肮脏和黑客,但它现在必须做。当我找到一个不需要使用.edmx文件的更好的解决方案时,也许我会回到它。

+0

你想使用EDMX – meda

+0

@meda如何做到这一点当然,它会派上用场,当我再次遇到类似的情况。 – dom