我在SQL Server中有一个表:
from itertools import count
class Node(object): # if on python3, you don't need to inherit from object
IDGEN = count()
def __init__(self, value):
self.id = self.IDGEN.next()
...
我试图用C#/ Entity Framework阅读:
select * from TaskSave
TaskID SaveTypeID ResultsPath PluginName PluginConfiguration
---------------------------------------------------------------------
92 1 NULL NULL NULL
92 7 NULL RGP_MSWord.WordDocumentOutput www|D:\Users\Peter\Documents\Temp
92 7 NULL RGP_WC.WCOutput wcwc|D:\Users\Peter\Documents\Temp|.docx|123|456|789
业务规则声明TaskID + SaveTypeID + PluginName是唯一的,即任务可以有多个插件。如果保存类型不是“插件”,则TaskID + SaveTypeID必须是唯一的。
我的问题是public static List<TaskSave> GetSavesPerTask(Task task)
{
using (Entities dbContext = new Entities())
{
var savesPerTask = from p in dbContext.TaskSaves.Include("SaveType").Where(q => q.TaskID == task.TaskID) select p;
//return savesPerTask.ToList();
// DEBUG
var x = savesPerTask.ToList();
foreach (var y in x)
{
Console.WriteLine("SaveTypeID {0}, Plugin Name {1}", y.SaveTypeID, y.PluginName);
}
return x;
}
}
方法返回错误的结果。它检索三行,但第2行是重复的 - 我得到GetSavesPerTask
PluginName
而不是RGP_MSWord.WordDocumentOutput
行的2行。调试打印显示:
RGP_WC.WCOutput
调试器和数据的最终用户都同意第三行不存在。
我尝试删除include子句,但这对结果集没有任何影响。以下是调试器报告的SQL(来自更简单的情况):
SaveTypeID 1, Plugin Name
SaveTypeID 7, Plugin Name RGP_MSWord.WordDocumentOutput
SaveTypeID 7, Plugin Name RGP_MSWord.WordDocumentOutput
我已将SQL从调试器复制并粘贴到SSMS中,并获得正确的结果。我尝试在EF模型中删除并重新创建这两个表。我已经多次重新编译,因为我尝试了不同的东西(添加调试,刷新模型,将返回移动到使用块之外等)。
savesPerTask {SELECT
[Extent1].[TaskID] AS [TaskID],
[Extent1].[SaveTypeID] AS [SaveTypeID],
[Extent1].[ResultsPath] AS [ResultsPath],
[Extent1].[PluginName] AS [PluginName],
[Extent1].[PluginConfiguration] AS [PluginConfiguration]
FROM (SELECT
[TaskSave].[TaskID] AS [TaskID],
[TaskSave].[SaveTypeID] AS [SaveTypeID],
[TaskSave].[ResultsPath] AS [ResultsPath],
[TaskSave].[PluginName] AS [PluginName],
[TaskSave].[PluginConfiguration] AS [PluginConfiguration]
FROM [dbo].[TaskSave] AS [TaskSave]) AS [Extent1]
WHERE [Extent1].[TaskID] = @p__linq__0}
表没有主键,所以我在编译期间得到错误6002(我忽略了它,因为它似乎没有影响其他任何东西,我在互联网上找不到任何解决办法)
'Database.dbo.TaskSave'没有定义主键。已推断密钥,并将定义创建为只读表/视图。
如何修复TaskSave
方法以返回正确的行?我犯了什么愚蠢的错误?我有许多其他表和CRUD操作,似乎按预期工作。
以下是我的版本
答案 0 :(得分:2)
最有可能,问题只是缺少明确的主键。数据库中的每个表格 无论如何都应该一个主键...
这里发生的事情是:由于没有主键,EF只会使用表格(或视图)中的所有非可空列作为&#34;替换&# 34; PK。不确定你的情况 - 可能(TaskID
,SaveTypeID
)??
当EF读取数据时,它将会:
所以在你的情况下,一旦它用&#34;替换&#34;读取第一行。 PK为TaskID = 92, SaveTypeID = 7
,具有这两个值的任何其他行只会得到已读取的值 - 无论数据库中存储了什么!
解决方案:正如我之前所说:每个表一直一个正确的主键唯一标识每一行!
在您的情况下,我建议只添加这样的代理键:
ALTER TABLE dbo.TaskSave
ADD TaskSaveID INT IDENTITY(1,1) NOT NULL
ALTER TABLE dbo.TaskSave
ADD CONSTRAINT PK_YourTableName
PRIMARY KEY CLUSTERED(TaskSaveID)
现在,每一行都有自己独特的TaskSaveID
,EF可以检测正确的PK,所有的麻烦都应该消失。