首页 > 解决方案 > 在实体框架中执行sql查询时如何绑定部分类的额外属性?

问题描述

我有一个具有动态 where 子句的 sql 查询:

 string qry= "select p.*,u.fname as username from Proforma p inner join users u on u.userid=p.userid where " + where1 + " and " + where2 + " and " + where3 + " order by p.userid,invoicedate desc";

我使用这个添加了额外的属性

namespace root.Models.db
{
    public partial class Proforma
    {
       public string username { get; set; }
    }
}

现在我正在尝试使用以下方法立即获取数据:

List<Proforma> pm = db.Database.SqlQuery<Proforma>(qry).ToList();

我期待它从数据库中获取用户名并相应地绑定。但它不起作用。

请帮忙。提前致谢。

标签: c#entity-framework

解决方案


详细说明设置用户和性能。

如果关系是一对一的关系,两个表共享一个 UserId 的 PK:

public class User 
{
  public int UserId {get; set;}
   // .. other User fields.

  public virtual Performa Performa {get; set;}
}

public class Performa
{
  public int UserId {get; set;}
  // .. other Performa fields.

  public virtual User User {get; set;}
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
  public UserConfiguration()
  {
    ToTable("Users");
    HasKey(x => x.UserId)
      .Property(x => x.UserId)
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

    HasRequired(x => x.Performa)
      .WithRequiredPrincipal(x => x.User);
  }
}

public class PerformaConfiguration : EntityTypeConfiguration<Performa>
{
  public PerformaConfiguration()
  {
    ToTable("Performas");
    HasKey(x => x.UserId)
      .Property(x => x.UserId)
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
  }
}

从那里我强烈建议使用 ViewModels / DTO 对象传回调用视图 / 代码,而不是传回实体。这避免了延迟加载带来的各种性能问题,并减少了从 DB 到客户端的数据量。

var performaQuery = db.Database.SqlQuery<Proforma>(qry);
var viewModels = performaQuery.Select(x => new PerformaViewModel 
{
  UserId = x.UserId,
  PerformaName = x.Name,
  UserName = x.User.Name
}).ToList();

使用这种方法,您可能可以减少或消除对动态查询的需求。如果您将实体映射到关系并希望通过说 UserName 与 PerformaName 或 InvoiceDate 来加载 Performa...

public IEnumerable<PerformaViewModel> LoadByCriteria(string userName = null, string performaName = null, DateTime? invoiceDate = null)
{
   var query = context.Performas.Where(x => x.IsActive); // Global filter example...
   if (!string.IsNullOrEmpty(userName))
     query = query.Where(x => x.User.UserName == userName);
   if (!string.IsNullOrEmpty(performaName))
     query = query.Where(x => x.PerformaName == performaName);
   if (invoiceDate.HasValue)
     query = query.Where(x => x.InvoiceDate == invoiceDate);

  var viewModels = query.Select(x => new PerformaViewModel 
  {
    UserId = x.UserId,
    PerformaName = x.Name,
    UserName = x.User.Name
  }).ToList();

  return viewModels;
}

这只是组成 Linq 表达式的一个基本示例。您需要详细说明上下文的范围,无论是使用工作单元还是 DB 上下文,其范围是请求并由 IoC 容器提供,还是使用using()块声明。EF 将使用条件 WHERE 子句执行该操作,必要时将适用的条件与一起 AND 并仅返回选定的字段。


推荐阅读