LINQ to SQL的 - 映射的异常使用抽象基类时 [英] LINQ to SQL - mapping exception when using abstract base classes

查看:130
本文介绍了LINQ to SQL的 - 映射的异常使用抽象基类时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:我想和大家分享多个组件之间code。这种共享code将需要与LINQ合作,SQL映射类。

Problem: I would like to share code between multiple assemblies. This shared code will need to work with LINQ to SQL-mapped classes.

我遇到同样的问题,发现 href=\"http://stackoverflow.com/questions/156113/linqtosql-and-abstract-base-classes\">,但我也发现,我觉得困扰(我不会那么远,说错误)一个变通。

I've encountered the same issue found here, but I've also found a work-around that I find troubling (I'm not going so far as to say "bug").

所有以下code可以在这个解决方案。

All the following code can be downloaded in 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映射:

and this DBML mapping:

<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>

我已经创建了下面的基类中的一个程序集共享:

I've created the following base classes in one assembly "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);
        }
    }
}

这些类另一个程序主引用,就像这样:

These classes are referenced in another assembly "Main", like so:

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

    }
}

该DBML文件位于主组装以及

The DBML file is located in the "Main" assembly, as well.

致电时 User.FindByName_Broken(DB,测试),则抛出异常:

System.InvalidOperationException:类成员UserBase.Name被取消映射

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

然而,另外两个基静态方法的工作。

However, the other two base static methods work.

此外,通过调用 User.FindByName_Works(DB,测试)生成的SQL是我们所希望看到的中碎电话:

Furthermore, the SQL generated by calling User.FindByName_Works(db, "test") is what we were hoping for in the broken call:

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 黑客单predicate查询,是否有共享的LINQ to SQL感知更好的办法在基本/共享/芯组装code?

While I am willing to use this 1 == 1 "hack" for single predicate queries, is there a better way of sharing LINQ to SQL-aware code in a base/shared/core assembly?

推荐答案

我也遇到这个问题很多次,在过去,因为我们在我们在我们公司使用的框架类似的架构。您可能已经注意到,如果你使用的声明样式LINQ查询,你会不会遇到这个问题。例如,下面的code将工作:

I have encountered this problem many times in the past because we have a similar architecture in a framework that we use in our company. You may have noticed that if you use the declarative style LINQ queries you'll not encounter this problem. For example the following code will work:

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

然而,由于我们使用的是动态过滤器前pressions我们不能使用这种方法。另一种解决方案是使用这样的:

However, since we are using dynamic filter expressions we couldn't use this method. The alternative solution is to use something like this:

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

此解决方案解决了我们的问题,因为我们可以注入一个。选择(I => I)到几乎所有的前pressions的开始。这将导致发动机的Linq不看的映射的基类,将迫使它来看看实际的实体类,并找到映射。

This solution solved our problem since we can inject a ".Select(i => i)" to the beginning of almost all expressions. This will cause the Linq engine not to look at the base class for the mappings and will force it to look at the actual entity class and find the mappings.

希望它能帮助

这篇关于LINQ to SQL的 - 映射的异常使用抽象基类时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆