WCF服务奇怪的行为:实体框架在运行代码时抛出异常,但在调试时工作正常

时间:2014-06-26 11:26:37

标签: c# entity-framework wcf debugging

我有一个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()

0 个答案:

没有答案