怎样解决三层中的主从表问题,急!望各位不啬赐教!(300分)

  • 主题发起人 主题发起人 jong
  • 开始时间 开始时间
J

jong

Unregistered / Unconfirmed
GUEST, unregistred user!
我在远程数模中建立主从关系:
A、主表数据集:qymaster,SqlText为‘Select * from Master’;数据源为DpMD,其中属性poFetchdetailsOnDemand为True,poAllowCommandText为True。
B、从表数据集(TADODataSet):QyDetail,CommandText为‘Select * from detail where ID=:ID’,DataSorurce设为‘dsmaster’,MasterFields为‘ID’。
在客户端新建两个TClientDataSet:
1、主表cdsMaster:数据源为DpMD。添加所有字段
2、从表cdsDetail:DataSetField为cdsDetail
但我新增时出现‘Insert语句与Column Foreign key约束‘Fk_Detail_Master’冲突,该冲突发生于数据库'Dataset1',表‘MASTER’,column 'ID'’
新增时ID并没有重复!
我试过很多方法都不行,因初学三层,特向熟悉三层的朋友请教解决主从关系问题。
最好能发源码例子,分不够可开另加三百分。望各位不啬赐教!
 
这个最好使用建立一个接口函数,自己使用SQL 写。不建议使用DATASOURCE进行连接。否则不好处理,冲突频繁。
 
同意蓝叶菱的
 
將代碼貼出幫你分析一下!
 
To :qinmingzsj
SQL Server数据库中 主表与从表设置了主从级联
服务器端没有什么函数、过程,只是一个远程模块,添加了主从关系的数据集,数据源。
unit rdm;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, Project1_TLB, StdVcl, DB, ADODB, MConnect, SConnect, Provider;
type
TDM = class(TRemoteDataModule, IDM)
MyDB: TADOConnection;
QyMaster: TADOQuery;
QyDetail: TADODataSet;
dsMaster: TDataSource;
DpMD: TDataSetProvider;
QyTemp: TADOQuery;
DpTemp: TDataSetProvider;
QyMasterID: TIntegerField;
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
override;
public
{ Public declarations }
end;

implementation
{$R *.DFM}
class procedure TDM.UpdateRegistry(Register: Boolean;
const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;

initialization
TComponentFactory.Create(ComServer, TDM,
Class_DM, ciMultiInstance, tmApartment);
end.


客户端:
unit client;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, DBClient, MConnect, SConnect, StdCtrls, Grids, DBGrids;
type
TForm1 = class(TForm)
sc: TSocketConnection;
cdsMaster: TClientDataSet;
DsMaster: TDataSource;
dsDetail: TDataSource;
cdsDetail: TClientDataSet;
dgmaster: TDBGrid;
dgdetail: TDBGrid;
btnAdd: TButton;
Button1: TButton;
cdsTemp: TClientDataSet;
cdsMasterID: TIntegerField;
cdsMasterQyDetail: TDataSetField;
procedure btnAddClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnAddClick(Sender: TObject);
var ID :integer;
begin
With cdsTempdo
begin
close;
FileName := '';
CommandText := 'Select Max(ID) from Master';
Open;
if Not cdstemp.Fields[0].isNull then
id:= cdstemp.Fields[0].AsInteger+1
else
ID := 1;
end;

With cdsMasterdo
begin
Append;
FindField('ID').AsInteger:= ID ;
Post;
end;

With cdsDetail do
begin
Append;
FindField('ID').AsInteger:= ID ;
FindField('Qty').AsInteger :=10;
Post;
end;
if cdsMaster.ApplyUpdates(0)>0 then
begin
showmessage('保存出错 !');
abort;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
try
sc.Open;
except
showmessage('连接失败!');
abort;
end;
with cdsMasterdo
begin
Close;
FileName :='';
CommandText := 'Select * from SalH Where 1<>1';
ProviderName := 'DpMd';
Open;
//SaveToFile(Application.ExeName+'a4.cds');
end;
end;

end.

初做三层,不知主从关系要如何做?
 
你把你的客户端的程序改写到服务器端就完了。
 
哈哈~~每次都在你(蓝叶菱)下面,坚决同意 蓝叶菱
 
如果是三层就用TClientDataSet吧..这个数据集挺好用的.
 
主表在窗体创建事件里面改了查询语句?
这样前后好像不一致吧
 
TO: jong
With cdsDetail do
begin
Append;
FindField('ID').AsInteger:= ID ;
FindField('Qty').AsInteger :=10;
Post;
end;
在構建了主從表之后,從表的增加不必使用 FindField('ID').AsInteger:= ID ;
而且在數據庫中應該將主從表的關聯關系設定好才可以在保存的時候不出現差錯,從你的代碼看來應該沒有什么問題.你使用clientdataset.delta 看看主從表是否有重復的ID值應該就可以看出問題在哪里
 
1 在服务器端不必设主从关系
2 在客户端设设主从关系
从表TClientDataSet
MasterFields = 'CategoryID'
MasterSource = DataSource1
3 从表的外键值不必赋值
把下面存成 Unit1.dfm
object Form1: TForm1
Left = 192
Top = 107
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object DBGrid1: TDBGrid
Left = 160
Top = 48
Width = 513
Height = 113
DataSource = DataSource1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object DBGrid2: TDBGrid
Left = 160
Top = 240
Width = 513
Height = 169
DataSource = DataSource2
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object Button1: TButton
Left = 16
Top = 112
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 2
OnClick = Button1Click
end
object Button2: TButton
Left = 64
Top = 336
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 3
OnClick = Button2Click
end
object DBNavigator1: TDBNavigator
Left = 176
Top = 16
Width = 240
Height = 25
DataSource = DataSource1
TabOrder = 4
end
object DBNavigator2: TDBNavigator
Left = 248
Top = 208
Width = 240
Height = 25
DataSource = DataSource2
TabOrder = 5
end
object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initi' +
'al Catalog=Northwind;Data Source=127.0.0.1'
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 96
Top = 72
end
object DataSetProvider1: TDataSetProvider
DataSet = ADOQuery1
Options = [poAllowCommandText]
Left = 152
Top = 120
end
object DataSetProvider2: TDataSetProvider
DataSet = ADOQuery2
Options = [poAllowCommandText]
Left = 168
Top = 176
end
object ClientDataSet1: TClientDataSet
Active = True
Aggregates = <>
AggregatesActive = True
CommandText =
'SELECT CategoryID, CategoryName, Description, Picture FROM Categ' +
'ories'
Params = <>
ProviderName = 'DataSetProvider1'
Left = 256
Top = 120
end
object ClientDataSet2: TClientDataSet
Active = True
Aggregates = <>
CommandText = 'SELECT * FROM Products'
IndexFieldNames = 'CategoryID'
MasterFields = 'CategoryID'
MasterSource = DataSource1
PacketRecords = 0
Params = <>
ProviderName = 'DataSetProvider2'
Left = 256
Top = 176
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
Parameters = <>
Left = 96
Top = 120
end
object ADOQuery2: TADOQuery
Connection = ADOConnection1
Parameters = <>
Left = 96
Top = 176
end
object DataSource1: TDataSource
DataSet = ClientDataSet1
Left = 296
Top = 128
end
object DataSource2: TDataSource
DataSet = ClientDataSet2
Left = 304
Top = 184
end
end
把下面存成 Unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, StdCtrls, Grids, DBGrids, ADODB, DBClient, Provider,
ExtCtrls, DBCtrls;
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
DataSetProvider1: TDataSetProvider;
DataSetProvider2: TDataSetProvider;
ClientDataSet1: TClientDataSet;
ClientDataSet2: TClientDataSet;
ADOQuery1: TADOQuery;
ADOQuery2: TADOQuery;
DBGrid1: TDBGrid;
DBGrid2: TDBGrid;
Button1: TButton;
DataSource1: TDataSource;
DataSource2: TDataSource;
Button2: TButton;
DBNavigator1: TDBNavigator;
DBNavigator2: TDBNavigator;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.ApplyUpdates(0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ClientDataSet2.ApplyUpdates(0);
end;

end.
 
TO:wangminqi
用两个CDS更新主从表我也想过,但这样的话我要将新增部分保存成本地CDS文件时要保存成两个文件。我是想通过嵌套表的形式保存主从表为一个CDS文件。以我的方法不知道可不可以实现。是否哪里设置错了?
 
看以前的贴子,嵌套表似乎有点问题
 
下面是嵌套表的例子,也是可以的
unit1.dfm
object Form1: TForm1
Left = 261
Top = 107
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object DBGrid1: TDBGrid
Left = 48
Top = 56
Width = 529
Height = 121
DataSource = DataSource2
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
Columns = <
item
Expanded = False
FieldName = 'CategoryID'
Visible = True
end
item
Expanded = False
FieldName = 'CategoryName'
Visible = True
end
item
Expanded = False
FieldName = 'Description'
Visible = True
end
item
Expanded = False
FieldName = 'Picture'
Visible = True
end>
end
object DBGrid2: TDBGrid
Left = 48
Top = 256
Width = 537
Height = 161
DataSource = DataSource3
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object Button1: TButton
Left = 56
Top = 24
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 2
OnClick = Button1Click
end
object Button2: TButton
Left = 56
Top = 232
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 3
end
object DBNavigator1: TDBNavigator
Left = 136
Top = 24
Width = 240
Height = 25
DataSource = DataSource2
TabOrder = 4
end
object DBNavigator2: TDBNavigator
Left = 200
Top = 224
Width = 240
Height = 25
DataSource = DataSource3
TabOrder = 5
end
object Button3: TButton
Left = 600
Top = 192
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 6
OnClick = Button3Click
end
object Edit1: TEdit
Left = 600
Top = 96
Width = 65
Height = 21
TabOrder = 7
Text = '10'
end
object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initi' +
'al Catalog=Northwind;Data Source=127.0.0.1'
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 8
Top = 72
end
object ADOTable1: TADOTable
Connection = ADOConnection1
CursorType = ctStatic
TableName = 'Categories'
Left = 88
Top = 72
end
object DataSource1: TDataSource
DataSet = ADOTable1
Left = 216
Top = 72
end
object DataSetProvider1: TDataSetProvider
DataSet = ADOTable1
Left = 352
Top = 80
end
object ClientDataSet1: TClientDataSet
Active = True
Aggregates = <>
Params = <>
ProviderName = 'DataSetProvider1'
Left = 432
Top = 80
object ClientDataSet1CategoryID: TAutoIncField
FieldName = 'CategoryID'
ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
end
object ClientDataSet1CategoryName: TWideStringField
FieldName = 'CategoryName'
Size = 15
end
object ClientDataSet1Description: TMemoField
FieldName = 'Description'
BlobType = ftMemo
end
object ClientDataSet1Picture: TBlobField
FieldName = 'Picture'
end
object ClientDataSet1ADOQuery1: TDataSetField
FieldName = 'ADOQuery1'
end
end
object ClientDataSet2: TClientDataSet
Active = True
Aggregates = <>
DataSetField = ClientDataSet1ADOQuery1
FieldDefs = <
item
Name = 'ProductID'
Attributes = [faReadonly]
DataType = ftAutoInc
end
item
Name = 'ProductName'
DataType = ftWideString
Size = 40
end
item
Name = 'SupplierID'
DataType = ftInteger
end
item
Name = 'CategoryID'
DataType = ftInteger
end
item
Name = 'QuantityPerUnit'
DataType = ftWideString
Size = 20
end
item
Name = 'UnitPrice'
DataType = ftBCD
Precision = 19
Size = 4
end
item
Name = 'UnitsInStock'
DataType = ftSmallint
end
item
Name = 'UnitsOnOrder'
DataType = ftSmallint
end
item
Name = 'ReorderLevel'
DataType = ftSmallint
end
item
Name = 'Discontinued'
DataType = ftBoolean
end>
IndexDefs = <
item
Name = 'DEFAULT_ORDER'
Fields = 'productid'
Options = [ixPrimary]
end>
Params = <>
StoreDefs = True
Left = 424
Top = 160
object ClientDataSet2ProductID: TAutoIncField
FieldName = 'ProductID'
ReadOnly = True
end
object ClientDataSet2ProductName: TWideStringField
FieldName = 'ProductName'
Size = 40
end
object ClientDataSet2SupplierID: TIntegerField
FieldName = 'SupplierID'
end
object ClientDataSet2CategoryID: TIntegerField
FieldName = 'CategoryID'
end
object ClientDataSet2QuantityPerUnit: TWideStringField
FieldName = 'QuantityPerUnit'
end
object ClientDataSet2UnitPrice: TBCDField
FieldName = 'UnitPrice'
Precision = 19
end
object ClientDataSet2UnitsInStock: TSmallintField
FieldName = 'UnitsInStock'
end
object ClientDataSet2UnitsOnOrder: TSmallintField
FieldName = 'UnitsOnOrder'
end
object ClientDataSet2ReorderLevel: TSmallintField
FieldName = 'ReorderLevel'
end
object ClientDataSet2Discontinued: TBooleanField
FieldName = 'Discontinued'
end
end
object DataSource2: TDataSource
DataSet = ClientDataSet1
Left = 512
Top = 80
end
object DataSource3: TDataSource
DataSet = ClientDataSet2
Left = 512
Top = 160
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
CursorType = ctStatic
DataSource = DataSource1
Parameters = <
item
Name = 'CategoryID'
Attributes = [paSigned, paNullable]
DataType = ftInteger
Precision = 10
Value = 1
end>
SQL.Strings = (
'select * from Products where CategoryID= :CategoryID')
Left = 88
Top = 176
end
end

unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, DBCtrls, StdCtrls, Grids, DBGrids, DB, DBClient,
Provider, ADODB;
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
ADOTable1: TADOTable;
DataSource1: TDataSource;
DataSetProvider1: TDataSetProvider;
ClientDataSet1: TClientDataSet;
ClientDataSet2: TClientDataSet;
DataSource2: TDataSource;
DataSource3: TDataSource;
DBGrid1: TDBGrid;
DBGrid2: TDBGrid;
Button1: TButton;
Button2: TButton;
DBNavigator1: TDBNavigator;
DBNavigator2: TDBNavigator;
ADOQuery1: TADOQuery;
ClientDataSet1CategoryID: TAutoIncField;
ClientDataSet1CategoryName: TWideStringField;
ClientDataSet1Description: TMemoField;
ClientDataSet1Picture: TBlobField;
ClientDataSet1ADOQuery1: TDataSetField;
ClientDataSet2ProductID: TAutoIncField;
ClientDataSet2ProductName: TWideStringField;
ClientDataSet2SupplierID: TIntegerField;
ClientDataSet2CategoryID: TIntegerField;
ClientDataSet2QuantityPerUnit: TWideStringField;
ClientDataSet2UnitPrice: TBCDField;
ClientDataSet2UnitsInStock: TSmallintField;
ClientDataSet2UnitsOnOrder: TSmallintField;
ClientDataSet2ReorderLevel: TSmallintField;
ClientDataSet2Discontinued: TBooleanField;
Button3: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.ApplyUpdates(0);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
//我取消了Categories表 CategoryID的自增
ClientDataSet1.Append;
ClientDataSet1.FieldByName('CategoryID').asinteger:=strtoint(edit1.Text );
ClientDataSet1.FieldByName('CategoryName').AsString :='aaaaaaa';
ClientDataSet1.Post;
ClientDataSet2.Append;
ClientDataSet2.FieldByName('productname').asstring:='aaabbb';
ClientDataSet2.Post;
end;

end.
 
多人接受答案了。
 
后退
顶部