我有一个WCF服务,即使用Entity Framework连接到数据库。我遇到了某种奇怪的行为 - 当我开始调试WCF服务并调用其中一种方法(Operation Contracts)时,根据我调试的方式,我会得到两种不同的场景。意思是,当我只是调用方法而没有插入代码时,我得到一个例外,说明:"违反PRIMARY KEY约束' PK_TagIsUsedInPublication'。无法在对象' dbo.TagIsUsedInPublication'中插入重复键。重复键值为(16,54)。"另一方面,当我在方法的开头放置一个断点并逐步进入代码并逐行浏览时,一切正常。这怎么可能,我做错了什么?
我的方法使用数据库中的两个实体 - Publication和Tag。我还有一个名为TagIsUsedInPublication的桥表。它有两个外键 - 一个指向Publication表,另一个指向Tag 1。它有一个复合主键,由两列(外键)组成。当然,这意味着Publication和Tag具有多对多的关系。
这是我的方法:
public static bool EditPublication(Interpretum.InterpretumService.SimplePublication publication)
{
try
{
InterpretumDAL.InterpretumEntities interpretumEntities = new InterpretumDAL.InterpretumEntities();
InterpretumDAL.Publication publicationDbContext =
(from p in interpretumEntities.Publications
where p.Id == publication.Id
select p).SingleOrDefault();
// This method just gets all the properties of my custom SimplePublication class and maps them to the Publication entity.
publicationDbContext = publication.ToDbContext(publicationDbContext);
if (publication.Tags.Count != 0)
{
publicationDbContext.Tags = Tag.RenderTagList(publication.Tags, publication.CreationUserId, interpretumEntities);
}
interpretumEntities.SaveChanges();
}
catch (Exception e)
{
// I added this throw line just to see what actually is causing the method fail.
throw e;
return false;
}
return true;
}
RenderTagList方法是必需的,因为我的模式需要Tag表的Name列的uniqe值。因此,它正在检查是否已经提供了名称的标签。如果有,则将其添加到标签列表中。如果不是,则创建一个新的,然后将其添加到列表中。
这是这个方法的样子:
public static List<InterpretumDAL.Tag> RenderTagList(List<SimpleTag> simpleTags, int creationUserId, InterpretumDAL.InterpretumEntities interpretumEntities)
{
List<InterpretumDAL.Tag> tags = new List<InterpretumDAL.Tag>();
foreach (var simpleTag in simpleTags)
{
InterpretumDAL.Tag tag = interpretumEntities.Tags.FirstOrDefault(x => x.Name == simpleTag.Name);
if (tag == null)
{
tag = new InterpretumDAL.Tag()
{
Name = simpleTag.Name,
CreationUserId = creationUserId
};
}
tags.Add(tag);
}
return tags;
}
正如我上面所写,当我刚刚调用EditPublication时,会抛出异常。当然,我每次使用相同的值调用它,无论我调用它多少次,我总是得到这个异常。但是,当我逐步进入代码并逐行遍历方法时,一切正常。
我必须提到我对Entity Framework相当新,所以我很可能做错了。问题在于我无法看到我做错了什么,只是因为这种不可预测的行为。
修改1:
堆栈追踪:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext`1 c)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)
at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery()
at System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.Execute(Dictionary`2 identifierValues, List`1 generatedValues)
at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()