Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ生成不正确的SQL(引用不存在的表)_C#_Asp.net Mvc 3_Linq_Entity Framework 4_Ef Model First - Fatal编程技术网

C# LINQ生成不正确的SQL(引用不存在的表)

C# LINQ生成不正确的SQL(引用不存在的表),c#,asp.net-mvc-3,linq,entity-framework-4,ef-model-first,C#,Asp.net Mvc 3,Linq,Entity Framework 4,Ef Model First,MVC3项目,先使用LINQ转换实体,然后使用实体框架4代码 在另一篇文章中,我在创建LINQ语句以返回数据子集方面得到了帮助 LINQ在语法上是正确的,可以编译,但会生成不正确的SQL。具体来说,它引用了一个不存在的表。如果我更正表名,它将返回正确的数据,因此LINQ似乎是正确的 注意:为了避免这篇长文章变得更长,我不会发布对象类Product、Tag和ProductTag,但它们列在我前面的问题中: 林克: 以下是不正确和正确的SQL代码 错误的SQL引用了不存在的表 [dbo].[Tag

MVC3项目,先使用LINQ转换实体,然后使用实体框架4代码

在另一篇文章中,我在创建LINQ语句以返回数据子集方面得到了帮助

LINQ在语法上是正确的,可以编译,但会生成不正确的SQL。具体来说,它引用了一个不存在的表。如果我更正表名,它将返回正确的数据,因此LINQ似乎是正确的

注意:为了避免这篇长文章变得更长,我不会发布对象类Product、Tag和ProductTag,但它们列在我前面的问题中:

林克:

以下是不正确和正确的SQL代码

错误的SQL引用了不存在的表

[dbo].[TagProduct] 
以及一个格式不正确的字段

[ExtentN].[Tag_TagId]
如果我将它们更正为[dbo].[ProductTag]和[ExtentN].[TagId],SQL将正确执行并返回正确的数据

LINQ生成了错误的SQL

正确的SQL

同样,SQL中唯一的变化是

[dbo].[TagProduct] changed to [dbo].[ProductTag]
[ExtentN].[Tag_TagId] changed to [ExtentN].[TagId]
注意,我已经确保数据库中没有名为dbo.TagProduct的对象,并且在我的代码中没有对TagProduct的引用,也从来没有

我的LINQ语句中是否有问题,或者这是一个LINQ错误?我完全可以放弃它,只创建一个存储过程,但我更愿意找到一个修复方法

感谢并为这篇冗长的帖子道歉

编辑

这个问题原来是一个有缺陷的实体模型,在多对多关系中的表之间有过多和不必要的导航属性。Slauma的详细回答是理解发生了什么的关键

新模式如下:

public class Product
{
    .
    . 
    //public virtual List<Tag> Tags { get; set; }             // <--removed
    public virtual List<ProductTag> ProductTags { get; set; }
}

public class ProductTag
{
    .
    . 
    public virtual Product Product { get; set; }
    public virtual Tag Tag { get; set; }
}

public class Tag
{
    .
    . 
    //public virtual List<Product> Products { get; set; }      // <--removed
    public virtual List<ProductTag> ProductTags { get; set; }

}

如果链接帖子中的模型中没有任何Fluent API中的其他映射,则生成的SQL是正确的。为什么?

为了清楚起见,我复制了您的模型,其中包含相关的导航属性和标记,它们属于一个整体:

public class Tag
{
    public int TagId { get; set; }

    public virtual List<Product> Products { get; set; }         /* 1 */
    public virtual List<ProductTag> ProductTags { get; set; }   /* 2 */
}

public class Product
{
    public int ProductId { get; set; }

    public virtual List<Tag> Tags { get; set; }                 /* 1 */
}

public class ProductTag
{
    public int ProductTagId { get; set; }

    public int ProductId { get; set; }
    public int TagId { get; set; }

    public virtual Product Product { get; set; }                /* 3 */
    public virtual Tag Tag { get; set; }                        /* 2 */
}
但这会产生问题,因为您已经有了一个ProductTag实体,它显然已经有了相应的表ProductTag。这不能同时成为多对多关系的联接表。联接表必须有另一个名称,如x.ToTableProductTagJoinTable

我想知道你是否真的想要这三种关系。或者,为什么希望表名ProductTag属于ProductTag实体?查询中根本不涉及此表和实体

编辑

更改模型的建议:除了多对多联接表所需的字段外,ProductTag实体不包含任何其他字段。因此,我将其映射为一个纯多对多关系。这意味着:

从模型中删除ProductTag实体类 从标记类中删除ProductTags导航属性 如上所示,在Fluent API中定义与名为ProductTag的联接表对应的映射,该联接表有两列ProductId和TagId,这两列构成复合主键,分别是Product和Tag表的外键
因此,在产品和标签之间只有一个多对多关系,而不是三个关系,我希望您的查询能够正常工作。

如果您在链接文章中的模型中没有Fluent API中的任何其他映射,则生成的SQL是正确的。为什么?

为了清楚起见,我复制了您的模型,其中包含相关的导航属性和标记,它们属于一个整体:

public class Tag
{
    public int TagId { get; set; }

    public virtual List<Product> Products { get; set; }         /* 1 */
    public virtual List<ProductTag> ProductTags { get; set; }   /* 2 */
}

public class Product
{
    public int ProductId { get; set; }

    public virtual List<Tag> Tags { get; set; }                 /* 1 */
}

public class ProductTag
{
    public int ProductTagId { get; set; }

    public int ProductId { get; set; }
    public int TagId { get; set; }

    public virtual Product Product { get; set; }                /* 3 */
    public virtual Tag Tag { get; set; }                        /* 2 */
}
但这会产生问题,因为您已经有了一个ProductTag实体,它显然已经有了相应的表ProductTag。这不能同时成为多对多关系的联接表。联接表必须有另一个名称,如x.ToTableProductTagJoinTable

我想知道你是否真的想要这三种关系。或者,为什么希望表名ProductTag属于ProductTag实体?查询中根本不涉及此表和实体

编辑

更改模型的建议:除了多对多联接表所需的字段外,ProductTag实体不包含任何其他字段。因此,我将其映射为一个纯多对多关系。这意味着:

从模型中删除ProductTag实体类 从标记类中删除ProductTags导航属性 如上所示,在Fluent API中定义与名为ProductTag的联接表对应的映射,该联接表有两列ProductId和TagId,这两列构成复合主键,分别是Product和Tag表的外键
因此,产品和标签之间只有一个多对多关系,而不是三个关系,我希望您的查询能够正常工作。

Um,这不是HTML。。。那是SQL。。。听起来您的模型可能与您的模式过时了。看起来您在没有重新创建本应具有的数据库的情况下更改了模型
将错误的LINQ查询更改为我给您的正确查询…在指定HTML而不是SQL时说不出话来;编辑文章。此外,链方法查询中的剪切/粘贴错误。我试着把它转换成linq,这就是我想到的。无论哪种方式,两个版本(包括您的版本)都会生成相同的错误SQL并抛出运行时错误。至于已经过时的模型,我没有任何产品表或模型。我昨天刚刚创建了dbo.ProductTag及其模型。所以我不相信它过时了…嗯,那不是HTML。。。那是SQL。。。听起来你的模型可能与你的模式过时了。看起来你在没有重新创建数据库的情况下更改了模型。你应该将错误的LINQ查询更改为我给你的正确查询…无言地过度指定HTML而不是SQL;编辑文章。此外,链方法查询中的剪切/粘贴错误。我试着把它转换成linq,这就是我想到的。无论哪种方式,两个版本(包括您的版本)都会生成相同的错误SQL并抛出运行时错误。至于已经过时的模型,我没有任何产品表或模型。我昨天刚刚创建了dbo.ProductTag及其模型。所以我不认为它过时了……我不得不花一点时间来理解你的答案,然后我开始在应用程序的其他区域看到更多无效对象名dbo.TagProduct错误。就在那时,你的答案开始深入人心。我结束了从产品和标签中删除导航属性。必须重新构造gdoron提供的查询以反映这些更改,现在一切都正常了。我将编辑我的问题以显示最终产品。感谢您的帮助和详细的答复@约翰:我明白了。ProductTag实体中是否有其他标量属性?否则,产品和标签之间的多对多映射不需要它,但它也可以工作:我不得不花一点时间来理解您的答案,然后我开始在应用程序的其他区域看到更多无效对象名dbo.TagProduct错误。就在那时,你的答案开始深入人心。我结束了从产品和标签中删除导航属性。必须重新构造gdoron提供的查询以反映这些更改,现在一切都正常了。我将编辑我的问题以显示最终产品。感谢您的帮助和详细的答复@约翰:我明白了。ProductTag实体中是否有其他标量属性?否则,产品和标签之间的多对多映射不需要它,但它也可以工作:
public class Product
{
    .
    . 
    //public virtual List<Tag> Tags { get; set; }             // <--removed
    public virtual List<ProductTag> ProductTags { get; set; }
}

public class ProductTag
{
    .
    . 
    public virtual Product Product { get; set; }
    public virtual Tag Tag { get; set; }
}

public class Tag
{
    .
    . 
    //public virtual List<Product> Products { get; set; }      // <--removed
    public virtual List<ProductTag> ProductTags { get; set; }

}
public class Tag
{
    public int TagId { get; set; }

    public virtual List<Product> Products { get; set; }         /* 1 */
    public virtual List<ProductTag> ProductTags { get; set; }   /* 2 */
}

public class Product
{
    public int ProductId { get; set; }

    public virtual List<Tag> Tags { get; set; }                 /* 1 */
}

public class ProductTag
{
    public int ProductTagId { get; set; }

    public int ProductId { get; set; }
    public int TagId { get; set; }

    public virtual Product Product { get; set; }                /* 3 */
    public virtual Tag Tag { get; set; }                        /* 2 */
}
modelBuilder.Entity<Product>()
    .HasMany(p => p.Tags)
    .WithMany(t => t.Products)
    .Map(x =>
    {
        x.MapLeftKey("ProductId");
        x.MapRightKey("TagId");
        x.ToTable("ProductTag");
    });