0

我试图理解为什么 Linq to Sql 为子实体生成插入语句而不是插入父实体。我正在使用两个表:WorkOrders 和 Boats。工作订单除其他外还有一条船。在我添加工作订单的表单上,我允许用户为选定的客户添加新船。如果他们选择添加新船而不是选择现有船,则会向他们提供另一种表格以添加船/船。每次我尝试保存新船时,它都会尝试插入工作订单。下面,我包含了两个类的 Linq 到 Sql 映射的子集、用于在 WorkOrders 和 Boats 之间创建外键的 sql 服务器脚本、我的 C# 保存逻辑、生成的 linq-to-sql 语句以及调用堆。有人可以告诉我这里可能发生的事情吗?

我已经检查了添加新船只的表格,并且它没有参考工作订单,因此我知道在保存之前我没有在船只上设置工作订单。此外,我可以使用该表格添加新船只,而无需浏览工作订单屏幕,而不会出现此问题。

标记

 <Table Name="dbo.Boats" Member="Boats">
    <Type Name="Boat">
      <Column Name="recno" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" />
      <Column Name="EditedDateTime" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />
      <Column Name="AddDateTime" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />
      <Association Name="Boat_WorkOrder" Member="WorkOrders" ThisKey="recno" OtherKey="Vessel" Type="WorkOrder" />
    </Type>
 </Table>

SQL

 ALTER TABLE [dbo].[WorkOrders]  WITH CHECK ADD  CONSTRAINT [FK_WorkOrders_Vessel] FOREIGN KEY([Vessel])
    REFERENCES [dbo].[Boats] ([recno])

    INSERT INTO [dbo].[WorkOrders]([CustomerFullName], [ClassListID], [ClassFullName], [ARAccountListId], [ARAccountFullName], [TemplateListID], [TemplateFullName], [InvoiceDate], [BillingAddress1], [BillingAddress2], [BillingAddress3], [BillingAddress4], [BillingAddress5], [BillingCity], [BillingState], [BillingPostalCode], [BillingCountry], [BillingNote], [ShippingAddress4], [ShippingAddress5], [TermsListID], [TermsFullName], [SalesRepListID], [SalesRepFullName], [Memo], [CustomerMessageListID], [CustomerMessageFullName], [OrderType], [OrderStatus], [Technician], [StartDate], [EstCompletionDate], [CompletionDate], [Vessel], [ShippingAddress1], [ShippingAddress2], [ShippingAddress3], [ShippingCity], [ShippingState], [ShippingPostalCode], [ShippingCountry], [PONumber], [ShippingNote], [Symptoms], [Notes], [AddDateTime], [AddBy], [EditedDateTime], [EditedBy], [TransactionStatus], [SyncStatus], [CustomerListId], [CustomerId], [Location])
    VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46, @p47, @p48, @p49, @p50, @p51, @p52, @p53)

C#

  private void saveBoat()
    {
        try
        {
            if (operationType == GlobalCollections.dbOperationType.Update)
            {
                currentBoat.AddBy = "user";
                currentBoat.AddDateTime = DateTime.Now;
                currentBoat.EditedBy = "user";
                currentBoat.EditedDateTime = DateTime.Now;

                dao.UpdateEntity(currentBoat, false);
            }
            else if (operationType == GlobalCollections.dbOperationType.Insert)
            {
                currentBoat.AddBy = "user";
                currentBoat.AddDateTime = DateTime.Now;
                currentBoat.EditedBy = "user";
                currentBoat.EditedDateTime = DateTime.Now;
                dao.AddEntity(currentBoat);
            }
        }
        catch (Exception ex)
        {
            GlobalCollections.showAndLogErrors(logger, ex);
        }
    }

堆栈跟踪

09/06/2012 09:36:15 Error BEN-LAPTOP MarineService.GlobalCollections.showAndLogErrors Cannot insert the value NULL into column 'AddDateTime', table 'ScribbleSoft.dbo.WorkOrders'; column does not allow nulls. INSERT fails.
The statement has been terminated.
09/06/2012 09:36:15 Error BEN-LAPTOP MarineService.GlobalCollections.showAndLogErrors    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   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)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
   at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
   at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   at System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)
   at System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)
   at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
   at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
   at System.Data.Linq.DataContext.SubmitChanges()
   at Scribble.Database.Utilities.Domain.Persistence.Repository`1.SaveAll() in C:\Aaron\Dev\HIGH PRIORITY\ServiceModule\MarineService\PureService.DatabaseAccess\Scribble.Database.Utilities\Domain\Persistence\Repository.cs:line 69
   at Scribble.Database.Utilities.Domain.Persistence.Repository`1.UpdateEntity(T entity, Boolean attach) in C:\Aaron\Dev\HIGH PRIORITY\ServiceModule\MarineService\PureService.DatabaseAccess\Scribble.Database.Utilities\Domain\Persistence\Repository.cs:line 43
   at MarineService.Tests.AddVesselForm.saveBoat() in C:\Aaron\Dev\HIGH PRIORITY\ServiceModule\MarineService\ServiceModule\AddVesselForm.cs:line 207
4

2 回答 2

0

两天后,我终于弄清楚了我的问题。简而言之,我有一个用于添加工单的表单。表单具有用于填充表单的 WorkOrder 的类变量。一个 WorkOrder 可以有一个 Vessel 和一个 Customer。我的问题是船只与客户有关系,而客户又与 WorkOrder 有关系。一旦用户选择了客户,客户就被设置到工作订单上。然后,当用户尝试添加或更新船时,Linq 检测到该船已附加到已附加到 WorkOrder 的客户。这解释了为什么框架在尝试插入或更新新船之前为工作订单生成插入。

现在,我已经修改了表单,以便我修改或访问支持表单的 WorkOrder 的唯一时间是加载和保存。否则,我在我的控件上使用 text 或 tag 属性。

于 2012-09-07T01:12:00.447 回答
0

您也许可以使用Attach.

你会做类似的事情

context.WorkOrders.Attach(currentBoat.WorkOrder);

这告诉上下文 WorkOrder 是一个现有对象,应该与数据库相关联,但不能像“新”项目那样插入。

于 2012-09-07T01:41:09.740 回答