c# - LINQ to SQL - 使用抽象基类时的映射异常

标签 c# linq-to-sql abstract-class

问题:我想在多个程序集之间共享代码。此共享代码将需要与 LINQ to SQL 映射类一起使用。

我遇到了同样的问题 here ,但我也发现了一个我觉得麻烦的解决方法(我不会说“错误”)。

以下所有代码都可以在this solution中下载.

给定这张表:

create table Users
(
      Id int identity(1,1) not null constraint PK_Users primary key
    , Name nvarchar(40) not null
    , Email nvarchar(100) not null
)

和这个 DBML 映射:

<Table Name="dbo.Users" Member="Users">
  <Type Name="User">
    <Column Name="Id" Modifier="Override" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" />
    <Column Name="Name" Modifier="Override" Type="System.String" DbType="NVarChar(40) NOT NULL" CanBeNull="false" />
    <Column Name="Email" Modifier="Override" Type="System.String" DbType="NVarChar(100) NOT NULL" CanBeNull="false" />
  </Type>
</Table>

我在一个“共享”程序集中创建了以下基类:

namespace TestLinq2Sql.Shared
{
    public abstract class UserBase
    {
        public abstract int Id { get; set; }
        public abstract string Name { get; set; }
        public abstract string Email { get; set; }
    }

    public abstract class UserBase<TUser> : UserBase where TUser : UserBase
    {
        public static TUser FindByName_Broken(DataContext db, string name)
        {
            return db.GetTable<TUser>().FirstOrDefault(u => u.Name == name);
        }

        public static TUser FindByName_Works(DataContext db, string name)
        {
            return db.GetTable<TUser>().FirstOrDefault(u => u.Name == name && 1 == 1);
        }

        public static TUser FindByNameEmail_Works(DataContext db, string name, string email)
        {
            return db.GetTable<TUser>().FirstOrDefault(u => u.Name == name || u.Email == email);
        }
    }
}

这些类在另一个程序集“Main”中被引用,如下所示:

namespace TestLinq2Sql
{
    partial class User : TestLinq2Sql.Shared.UserBase<User>
    {

    }
}

DBML 文件也位于“主”程序集中。

当调用 User.FindByName_Broken(db, "test") 时,抛出异常:

System.InvalidOperationException: Class member UserBase.Name is unmapped.

但是,其他两个基本静态方法有效。

此外,通过调用 User.FindByName_Works(db, "test") 生成的 SQL 正是我们在中断的调用中所希望的:

SELECT TOP (1) [t0].[Id], [t0].[Name], [t0].[Email]
FROM [dbo].[Users] AS [t0]
WHERE [t0].[Name] = @p0
-- @p0: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [test]

虽然我愿意将此 1 == 1 “hack”用于单个谓词查询,但是否有更好的方法在基础/共享/核心程序集中共享 LINQ to SQL 感知代码?

最佳答案

这个问题我以前遇到过很多次,因为我们公司用的一个框架有类似的架构。您可能已经注意到,如果您使用声明式 LINQ 查询,则不会遇到此问题。例如,以下代码将起作用:

return (from i in db.GetTable<TUser>() where i.Name = "Something").FirstOrDefault();

但是,由于我们使用的是动态过滤器表达式,因此无法使用此方法。另一种解决方案是使用这样的东西:

return db.GetTable<TUser>().Select(i => i).Where(i => i.Name == "Something").SingleOrDefault();

这个解决方案解决了我们的问题,因为我们可以在几乎所有表达式的开头插入一个“.Select(i => i)”。这将导致 Linq 引擎不查看映射的基类,而是强制它查看实际的实体类并找到映射。

希望对你有帮助

关于c# - LINQ to SQL - 使用抽象基类时的映射异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1021274/

相关文章:

c# - 调用方法时起订量验证属性

c# - LINQ to Entities 仅支持无参数构造函数和初始值设定项

linq-to-sql - 使用 LINQ 返回唯一记录

c++ - 需要从DLL导出纯基类?

c# - Entity Framework 4 抽象模型 - 如何以编程方式预加载导航属性?

c# - 如何将字符串列表序列化为 objectid 列表

c# - 使用 Json.NET 序列化 : how to require a property not being null?

c# 将 var 声明为接口(interface)。为什么这可能?

asp.net-mvc - Viewmodel 和 LINQ 查询表示 Asp.Net MVC 中的 4 个链接表

c# - 抽象方法使用与常规方法