Jar*_*xon 21 c# abstract-class linq-to-sql
问题:我想在多个程序集之间共享代码.这个共享代码需要使用LINQ to SQL映射类.
我在这里遇到了同样的问题,但我也找到了一个解决问题的方法(我不会说"bug").
可以在此解决方案中下载以下所有代码.
鉴于此表:
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
)
Run Code Online (Sandbox Code Playgroud)
和这个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>
Run Code Online (Sandbox Code Playgroud)
我在一个程序集"Shared"中创建了以下基类:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些类在另一个程序集"Main"中引用,如下所示:
namespace TestLinq2Sql
{
partial class User : TestLinq2Sql.Shared.UserBase<User>
{
}
}
Run Code Online (Sandbox Code Playgroud)
DBML文件也位于"Main"程序集中.
调用时User.FindByName_Broken(db, "test"),会抛出异常:
System.InvalidOperationException:类成员UserBase.Name未映射.
但是,其他两个基本静态方法都有效.
此外,通过调用生成的SQL User.FindByName_Works(db, "test")是我们在破坏的调用中希望的:
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]
Run Code Online (Sandbox Code Playgroud)
虽然我愿意将这个1 == 1"hack"用于单个谓词查询,但是有更好的方法在基础/共享/核心程序集中共享LINQ to SQL感知代码吗?
red*_*ver 19
我过去曾多次遇到过这个问题,因为我们在公司的框架中有类似的架构.您可能已经注意到,如果使用声明式LINQ查询,则不会遇到此问题.例如,以下代码将起作用:
return (from i in db.GetTable<TUser>() where i.Name = "Something").FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
但是,由于我们使用的是动态过滤器表达式,因此无法使用此方法.替代解决方案是使用这样的东西:
return db.GetTable<TUser>().Select(i => i).Where(i => i.Name == "Something").SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)
这个解决方案解决了我们的问题,因为我们可以在几乎所有表达式的开头注入".Select(i => i)".这将导致Linq引擎不查看映射的基类,并强制它查看实际的实体类并找到映射.
希望能帮助到你
尝试在Where子句之前包含OfType
return _dbContext.GetTable<T>().OfType<T>().Where(expression).ToList();
| 归档时间: |
|
| 查看次数: |
4598 次 |
| 最近记录: |