【问题标题】:Entity Framework Core - one model for multiple queriesEntity Framework Core - 一个模型用于多个查询
【发布时间】:2019-09-13 16:43:24
【问题描述】:

我有一个使用 Entity Framework Core 的 .NET Core API。我们使用.FromSQL() 来执行存储过程。我遇到的问题是我们有两个查询返回Account 信息——一个用于单个帐户,一个用于分页帐户列表。

帐户列表返回RowCount 的列,单帐户查询不返回,所以现在单帐户查询返回错误(Rowcount 返回数据库中的帐户总数,而不仅仅是帐户请求的页面,以便您知道有多少页数据)。

错误:

“FromSql”操作的结果中不存在所需的列“RowCount”

这是模型

public class Account
{
    [Key]
    public long AccountId { get; set; }

    public string AccountName { get; set; }
    public bool IsDeleted { get; set; }
    public int RowCount { get; set; }

    [NotMapped]
    public bool Found => AccountId > 0;
}

还有我们的 dbContext

public class AccountDbContext : DbContext
{
    private DbSet<Account> TAccount { get; set; }

    public AccountDbContext(DbContextOptions<AccountDbContext> options) : base(options)
    {
    }

    public Account GetAccountById(long accountId)
    {
        var pAccount = new SqlParameter("accountId", accountId);
        Account account = TAccount.FromSql("EXEC dbo.SPR_Account_GetById @accountId", pAccount).FirstOrDefault();
        return account;
    }

    public List<Account> GetAccounts(int offset, int limit)
    {
        var pOffset = new SqlParameter("offset", offset);
        var pLimit = new SqlParameter("limit", limit);

        var dataSet = TAccount.FromSql($"EXEC dbo.SPR_Account_GetAll @offset=@offset,@limit=@limit", pOffset, pLimit).ToList();

        return dataSet;
    }
}

我的问题:有没有办法为这两个查询重用这个模型?我认为创建具有相同属性的第二个模型是愚蠢的。而且我永远无法让实体与继承相得益彰。它总是给我一个关于找不到Discrimitator 的错误。

【问题讨论】:

  • 是否可以选择更改您的 GetById 存储过程以返回行数 1?
  • 当然。看起来像一个黑客。我希望有一些我可以使用的属性或配置。
  • 这是设计使然。您可以与 FromSql 方法一起使用的 SQL 中有一些限制。首先,也是最重要的,您必须确保您的结果包含 Entity Framework Core 将创建的实体类的每个属性的列,并且这些列必须与这些属性具有相同的名称。您只能通过其 DbSet 查询特定实体类,并且不能包含相关数据,这意味着您无法查询类,除非它们是数据模型的一部分。 Entity Framework Core 不会创建相关对象,即使您在原始 SQL 查询中包含 JOIN。
  • 我想了很多,我只是希望有一种方法可以覆盖这种行为,例如使用 [NotMapped] 来获取其他字段。如果我将行数移动到子类,关于我的鉴别器错误有什么想法吗? ` public class AccountCount : Account { public int RowCount { get;放; } }`
  • 好吧,[NotMapped] 实际上会阻止它甚至绑定。但这意味着您的行数也不会绑定到您的 GetAll 存储过程,所以这是没有选择的。如果您能够影响或更改数据库的设计,那么 Entity Framework Core 对视图的支持更加灵活。您的视图可以返回所需的行数,然后您的实体会很高兴。您的继承选项会给您带来更多困难,然后只返回 1 的行数。

标签: c# asp.net-core entity-framework-core


【解决方案1】:

感谢 Chris Pratt 和 Dennis1679,我进一步研究了继承。当基类和派生类都注册为可查询类型时,Entity Framework 不喜欢它。我创建了一个具有公共属性的基类和两个派生类:一个用于单个帐户,一个用于包含 RowCount 属性的列表。我对假继承不是 100% 满意,但我不必从存储的过程中返回一个虚拟的 RowCount,也不必复制我的对象。

public class AccountBase
{
    [Key]
    public long AccountId { get; set; }

    public string AccountName { get; set; }
    public bool IsDeleted { get; set; }

    [NotMapped]
    public bool Found => AccountId > 0;
}

public class AccountDataModel : AccountBase
{
}

public class AccountCount : AccountBase
{
   public int RowCount { get; set; }
}

然后,在我的 dbContext 中:

public class AccountDbContext : DbContext
{
    private DbSet<AccountDataModel> TAccount { get; set; }
    private DbSet<AccountCount> AccountList { get; set; }

    public AccountDbContext(DbContextOptions<AccountDbContext> options) : base(options)
    {
    }

    public Account GetAccountById(long accountId)
    {
        var pAccount = new SqlParameter("accountId", accountId);
        Account account = TAccount.FromSql("EXEC dbo.SPR_Account_GetById @accountId", pAccount).FirstOrDefault();
        return account;
    }

    public List<Account> GetAccounts(int offset, int limit)
    {
        var pOffset = new SqlParameter("offset", offset);
        var pLimit = new SqlParameter("limit", limit);

        var dataSet = AccountList.FromSql($"EXEC dbo.SPR_Account_GetAll @offset=@offset,@limit=@limit", pOffset, pLimit).ToList();

        return dataSet;
    }
}

【讨论】:

  • 听上去很好地利用了继承——大多数设计都涉及到一定程度的妥协,所以不要让完美成为美好的阻碍。
【解决方案2】:

为了将FromSql 与实体一起使用,返回的内容与实体上的属性之间必须存在直接的一对一关联。这不是可选的,也没有其他选择。

但是,如果您使用 DTO 类,则可以为所欲为。您只需将其添加到您的上下文中,例如:

public DbQuery<AccountDTO> AccountDTOs { get; set; }

然后您可以在上面使用FromSql,而不会遇到您遇到的任何问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2022-01-25
    • 2020-09-11
    • 1970-01-01
    相关资源
    最近更新 更多