DataSnap仅在插入后使用AutoInc键并刷新当前记录

时间:2014-11-13 02:25:12

标签: delphi auto-increment datasnap

我无法在任何地方找到答案。使用Delphi XE7和TClientDataSet,DataSnap& SQL Server。我需要插入一条记录,应用更新,然后刷新该记录,以便我可以获取Id并将其分配给我的对象。似乎是相当基本的要求,但恰恰相反,它被证明是一种皇室般的痛苦。

我在EDN上找到了明显的东西,SO和Bob博士:

http://edn.embarcadero.com/article/20847

DataSnap and the autoinc field

http://www.drbob42.com/examines/examinC0.htm

然而,这些似乎专注于TClientDataSet的“刷新”以重新获取整个表/查询。虽然这确实解决了Id字段本身(好!),但它也将光标移出刚插入的当前记录,因此我无法获取Id并将其分配给我的对象。另外,对于基于HTTP的性能,我不想在每次插入记录时都重新获取整个表,如果有10,000条记录,这将消耗太多带宽并且速度非常慢!

请考虑以下代码:

function TRepository<I>.Insert(const AEntity: I): I;
begin
  FDataSet.DisableControls;
  try
    FDataSet.Insert;
    AssignEntityToDataSet(AEntity);  // SET'S ALL THE RELEVANT FIELDS
    FDataSet.Post;
    FDataSet.ApplyUpdates(-1);
    FDataSet.Refresh;  // <--- I tried RefreshRecord here but it cannot resolve the record
    AEntity.Id := FDataSet.FieldByName('Id').AsInteger; // <----- THIS NOW POINTS TO WRONG ROW
  finally
    FDataSet.EnableControls;
  end;
end;

有谁知道如何实现这一目标?我需要能够刷新并保持当前记录,否则我不知道刚刚创建的记录的ID,并且GUI无法专注于当前记录。

希望显而易见的是我错过了。

干杯。 瑞克。

2 个答案:

答案 0 :(得分:2)

假设您可以在DataProvider的AfterUpdateRecord事件中获取新ID,那么您的事件处理程序可能如下所示(DeltaDS的当前记录是刚刚插入到SourceDS中的记录):

  if (UpdateKind = ukInsert) then begin
    DeltaDS.FindField('Id').NewValue := <TheNewID>;
  end;

确保在提供程序中设置了poPropogateChanges选项。这会将已更改的 Id 字段传回ClientDataSet。

现在你可以摆脱FDataSet.Refresh电话。

答案 1 :(得分:1)

SQL Server允许您以多种方式获取它生成的最后一个身份 - 不需要&#34;刷新&#34;记录/查询意味着重新发出SELECT并且可以产生不可容忍的副作用。您可以使用SELECT SCOPE_IDENTITY()或使用OUTPUT子句。如果Delphi数据库驱动程序支持它,TField.AutogenerateValue应自动完成该任务(参见http://docwiki.embarcadero.com/Libraries/XE7/en/Data.DB.TField.AutoGenerateValue

否则你必须将新数据放入delta(请参阅Raabe回答 - 这必须在读取数据库的数据库服务器上完成),然后将其发送回客户端。您还需要正确设置TField.ProviderFlags以确保正确应用数据(请参阅http://docwiki.embarcadero.com/RADStudio/XE7/en/Influencing_How_Updates_Are_Applied),通常您不希望这些字段出现在更新中。