Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.05.18;
Скачать: CL | DM;

Вниз

Ошибка "некоторые записи могли быть изменены"   Найти похожие ветки 

 
SuperNick   (2007-12-13 12:33) [0]

Здравствуйте!
Есть программа на Дельфи7, БД на Access, связь по ADO.  Я приведу фрагмент для примера. В БД существуют 2 таблицы, фактически их можно свести в одну, но в силу требований к программе и БД (таблицы будут заполняться в разное время и разными людьми), чтобы никто не мог испортить чужие данные (или более важные данные), таблиц реализовано 2 штуки.

Table1 (точки):
Id_point (счетчик, PK)
Name_point
Параметр

Table2 (напряжение в точках):
Id_point (FK на Table1)
Напряжение 1
….
Две таблички можно свести в одну и разными способами показывать пользователю те или другие столбцы для заполнения. По постановке - отпадает. Для надежности – разделение на 2 таблицы в БД. В итоге – связь между Table1 и Table2 – “один-к-одному”.
А вот пользователю для редактирования таблицы требуется представить в виде одной (вывести ее в DBGrid). Реализовано с помощью AdoQuery и запроса на объединение Left outer join (при этом записи, для которых не заданы значения в Table2 также выводятся, можно ввести значения). В принципе, все хорошо, но вот проблема, связанная с ADO, а именно: при попытке добавить запись в Table2 - сообщение "Некотороые значения могли быть изменены со времени последнего чтения". При этом выполнены все советы, что знал сам и прочитал про ADO:
- родительская запись в Table1 присутствует;
- уникальные первичные ключи есть во всех таблицах;
- TADODataSet(DataSet).Properties["Unique Table"].Value:=<имя Table 2> присутствует;
- TADODataSet(DataSet).Properties["Update Resync"].Value:=15{adResyncAll} присутствует;
- TADODataSet(DataSet).Properties["Update Criteria"].Value:=0{adCriteriaKey} присутствует;
- TADODataSet(DataSet).Properties["Resync Command"].Value:="select ..." - как описано в статьях об использовании ADO в Дельфи - присутствует;
- Настройки самой ADOQuery и ADOConnection корректны.
Что можно попробовать? Может быть, проблема еще в том, что запись добавляется в подчиненную таблицу в первый раз, первичного ключа, на который можно было бы ориентироваться еще нет (при операции редактирования существующей записи все работает).


 
ЮЮ ©   (2007-12-13 12:57) [1]

Похоже, в таком случае запись не INSERT-ится, а UPDATE-тся (ведь она в НД есть из-за левой части), а в таблице её не, отсюда и "некоторые записи могли быть изменены", т.е. запись вроде была а UPDATE не изменяет ни одной записи.

> Что можно попробовать?

Обой-ти "умную" АDO. Искать место в механизме, где можно послать иной запрос на сервер.


 
Anatoly Podgoretsky ©   (2007-12-13 13:07) [2]

Оно так и есть, данные будут изменены, тем же пользователем. Откажись от DbGrid и проблемм не будет.


 
Sergey13 ©   (2007-12-13 13:13) [3]

> [0] SuperNick   (13.12.07 12:33)
ИМХО сами создаем себе трудности и сами мужественно их преодолеваем.
Искусственное разбиение на 2 таблицы уже дает нормальные результаты.


 
Slym ©   (2007-12-14 13:43) [4]

Значения по умолчанию в базе убери


 
sniknik ©   (2007-12-14 17:13) [5]

ЮЮ ©   (13.12.07 12:57) [1]
> Искать место в механизме, где можно послать иной запрос на сервер.
чего его искать? "бефорепост" однозначно.

Slym ©   (14.12.07 13:43) [4]
> Значения по умолчанию в базе убери
именно здесь, это не причем. при других условиях возможно...

> - Настройки самой ADOQuery и ADOConnection корректны.
вот это меня всегда умиляет... хот и не работает, но неважно, все одно полная уверенность "я все правильно сделал! а виноват в "неработе" ктото другой. естественно."

у тебя даже в показанном мизере есть ошибка, а уж сколько их в "волшебных пузырьках"...  (точки и умолчания имеются ввиду), только догадываться.
ошибка
> - TADODataSet(DataSet).Properties["Unique Table"].Value:=<имя Table 2> присутствует;
а должно бы присутствовать "имя Table 1" т.к. у тебя связь сам пишешь второй таблице к первой, и во второй есть пропуски, т.е. первая более полная, всегда имеет ключевое поле по которому можно обновить всю связку, а вот вторая в части полей имеет null в тех местах где нет совпадений, а по null  какие могут быть операции?

в общем исправить это, плюс заменить апдейт на инсерт (см. [1]) когда необходимо, и если ничего больше из "пузырьков" не вылезет, должно работать.


 
sniknik ©   (2007-12-14 17:46) [6]

вот, накидал пример, вполне рабочий, остались конечно неувязочки... но даже думать на эту тему неохота. (и так все изза идиотского проектирования)
в общем, при добавлении записи (пост в гриде по стрелке вниз, вверх) курсор остается на месте, надо жать 2 раза, не так как при редактировании.
ну и невозможность добавлять записи в первую (основную) таблицу, т.к. чтобы получить автоинкремент нужно запостить запись, а мы этого не можем т.к. нет значения для второй таблицы. замкнутый круг однако... (решить конечно можно, еще одной вариацией запроса для этого случая, но нафик)

код
unit Unit2;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Grids, DBGrids, DB, ADODB, ADOInt;

type
 TForm1 = class(TForm)
   ADOConnection1: TADOConnection;
   ADODataSet1: TADODataSet;
   DataSource1: TDataSource;
   DBGrid1: TDBGrid;
   ADOCommand1: TADOCommand;
   procedure FormCreate(Sender: TObject);
   procedure ADODataSet1AfterOpen(DataSet: TDataSet);
   procedure ADODataSet1BeforePost(DataSet: TDataSet);
 private
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 //предварительно создать таблицы в базе ttt.mdb (или исправить коннект и т.д)
 //CREATE TABLE LTable (ID INT Identity(1, 1) PRIMARY KEY, Name VarChar(50))
 //CREATE TABLE RTable (ID INT PRIMARY KEY, Name VarChar(50))

 ADODataSet1.Open;
 ADODataSet1.FieldByName("r.ID").Visible:= false;
end;

procedure TForm1.ADODataSet1AfterOpen(DataSet: TDataSet);
begin
 with TADODataSet(DataSet) do begin
   Properties["Update Criteria"].Value:= adCriteriaKey;
   Properties["Unique Table"   ].Value:= "LTable";
   Properties["Resync Command" ].Value:=
     "SELECT * FROM LTable l LEFT JOIN RTable r ON l.ID=r.ID WHERE l.ID=?";
 end;
end;

procedure TForm1.ADODataSet1BeforePost(DataSet: TDataSet);
begin
 with TADODataSet(DataSet) do
   if FieldByName("r.ID").IsNull then begin
     ADOCommand1.Parameters.ParamByName("ID"  ).Value:= FieldByName("l.ID"  ).AsInteger;
     ADOCommand1.Parameters.ParamByName("Name").Value:= FieldByName("r.Name").AsString;
     ADOCommand1.Execute;

     Cancel;
     Recordset.Resync(adAffectCurrent, adResyncAllValues);
     Resync([rmExact]);

     Abort;
   end;
end;

end.


и dfm
object Form1: TForm1
 Left = 251
 Top = 107
 Width = 747
 Height = 549
 Caption = "Form1"
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = "MS Sans Serif"
 Font.Style = []
 OldCreateOrder = False
 OnCreate = FormCreate
 PixelsPerInch = 96
 TextHeight = 13
 object DBGrid1: TDBGrid
   Left = 24
   Top = 80
   Width = 673
   Height = 369
   DataSource = DataSource1
   TabOrder = 0
   TitleFont.Charset = DEFAULT_CHARSET
   TitleFont.Color = clWindowText
   TitleFont.Height = -11
   TitleFont.Name = "MS Sans Serif"
   TitleFont.Style = []
 end
 object ADOConnection1: TADOConnection
   ConnectionString =
     "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=ttt.mdb;Persist Sec" +
     "urity Info=False"
   LoginPrompt = False
   Mode = cmShareDenyNone
   Provider = "Microsoft.Jet.OLEDB.4.0"
   Left = 48
   Top = 16
 end
 object ADODataSet1: TADODataSet
   Connection = ADOConnection1
   CursorType = ctStatic
   AfterOpen = ADODataSet1AfterOpen
   BeforePost = ADODataSet1BeforePost
   CommandText = "SELECT * FROM LTable l LEFT JOIN RTable r ON l.ID=r.ID "
   Parameters = <>
   Left = 104
   Top = 16
 end
 object DataSource1: TDataSource
   DataSet = ADODataSet1
   Left = 160
   Top = 16
 end
 object ADOCommand1: TADOCommand
   CommandText = "INSERT INTO RTable (ID,Name) VALUES (:ID,:Name)"
   Connection = ADOConnection1
   Parameters = <
     item
       Name = "ID"
       Attributes = [paNullable]
       DataType = ftWideString
       NumericScale = 255
       Precision = 255
       Size = 510
       Value = "0"
     end
     item
       Name = "Name"
       Attributes = [paNullable]
       DataType = ftString
       Size = 50
       Value = """"""
     end>
   Left = 224
   Top = 16
 end
end



Страницы: 1 вся ветка

Текущий архив: 2008.05.18;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.02 c
11-1189437864
Robt
2007-09-10 19:24
2008.05.18
PList


11-1189173120
MTsv DN
2007-09-07 17:52
2008.05.18
Вопрос по прозрачности, вероятно автору - homm у...


2-1208350865
papa_roarch
2008-04-16 17:01
2008.05.18
Правый или левый клик?


2-1208631399
Rasputin
2008-04-19 22:56
2008.05.18
поиск окна и родительских окон


2-1208326305
Mishenka
2008-04-16 10:11
2008.05.18
Как в TEdit определить в какой позиции находится курсор?