实体框架:无法创建类型<t>的常量值。只有原始类型或枚举t

时间:2016-02-28 22:00:49

标签: entity-framework

说我有以下SQL Server表:

CREATE TABLE ExampleTable (
    A INT NOT NULL,
    B INT NOT NULL,
    C INT NOT NULL,
    CONSTRAINT PK_A PRIMARY KEY CLUSTERED(A),
    CONSTRAINT UK_BC UNIQUE(B,C)
);

INSERT INTO ExampleTable VALUES (1, 0, 0);
INSERT INTO ExampleTable VALUES (2, 0, 1);
INSERT INTO ExampleTable VALUES (3, 1, 0);
INSERT INTO ExampleTable VALUES (4, 1, 1);

假设我知道条目的B和C值,我需要学习A值。我显然可以编写以下T-SQL查询:

SELECT * FROM [dbo].[ExampleTable] WHERE (B = 0 AND C = 0)  -- Returns (1,0,0)

但是,我希望以这种方式查找大量条目的图像,我希望将此查找作为单个数据库查询的一部分完成。我可以看到以下T-SQL查询:

SELECT * FROM [dbo].[ExampleTable] WHERE (B = 0 AND C = 0) OR (B = 1 AND C = 1) -- OR (Additional entity... Returns (1,0,0), (4,1,1), etc.

或者,我可以创建一个存储过程,在多列上进行连接:

CREATE TYPE BCPairsType AS TABLE (B INT, C INT);

CREATE PROCEDURE GetFromBAndC 
    @BCPairs BCPairsType READONLY
    AS
        SELECT ExampleTable.A, ExampleTable.B, ExampleTable.C 
        FROM ExampleTable 
        JOIN @BCPairs bcPairs ON 
        ExampleTable.B = bcPairs.B AND 
        ExampleTable.C = bcPairs.C
    GO

DECLARE @input AS BCPairsType;
INSERT INTO @input VALUES (0,0);
INSERT INTO @input VALUES (1,1);
-- Add entries as necessary 
EXEC GetFromBAndC @input -- Returns (1,0,0), (4,1,1), etc.

但是,现在我希望以一种不涉及编写和维护存储过程的方式在Entity Framework(v6.1.3)中解决这个问题。以下是我最终的逻辑:

EF模型+ POCO:

public partial class ExampleModel : DbContext
{
    public ExampleModel()
        : base("name=ExampleModel")
    {
    }

    public virtual DbSet<ExampleTable> ExampleTables { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    }
}

[Table("ExampleTable")]
public partial class ExampleTable
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int A { get; set; }

    public int B { get; set; }

    public int C { get; set; }
}

模仿策略的逻辑#1:

var model = new ExampleModel();
var pairsToLookup = new List<Tuple<int,int>>
{
    new Tuple<int, int>(0,0),
    new Tuple<int, int>(1,1)
};

var results =
    model.ExampleTables.Where(row => pairsToLookup.Contains(new Tuple<int, int>(row.B, row.C))).ToList();

模仿策略#2的逻辑:

var model = new ExampleModel();
var pairsToLookup = new List<Tuple<int, int>>
{
    new Tuple<int, int>(0,0),
    new Tuple<int, int>(1,1)
 };

 var q = from exampleTableValue in model.ExampleTables.AsQueryable()
     join inputTuple in pairsToLookup.AsQueryable()
     on new {b = exampleTableValue.B, c = exampleTableValue.C } equals new { b = inputTuple.Item1, c = inputTuple.Item2 }
     select exampleTableValue;

 var results = q.ToList();

然而,这两种策略都不起作用,我留下了以下错误:

  

System.NotSupportedException:无法创建类型&#39; System.Tuple`2 [[System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089],[System。 Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]&#39;。在此上下文中仅支持原始类型或枚举类型。

根据我所能提到的其他问题,由于实体框架将任意.NET代码转换为T-SQL的能力有限,因此引发此错误。 (EF声称它只支持原始类型或枚举类型。)但是,我无法看到任何明显的方法,我可以在任一策略中重写逻辑以使用原始类型,同时支持配对已知B和C值的概念。有没有人知道我可以让EF执行这个逻辑而不需要使用存储过程?

0 个答案:

没有答案