Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2008.05.18;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.049 c
2-1208858129
AlexAA
2008-04-22 13:55
2008.05.18
Открыть файл .exe


2-1208611624
Алексей К.
2008-04-19 17:27
2008.05.18
получение имен в TStringList


2-1208388475
deras
2008-04-17 03:27
2008.05.18
SQL - запрос


2-1208350222
Апостля
2008-04-16 16:50
2008.05.18
буфер. ричедит.


2-1208127399
HF-Trade
2008-04-14 02:56
2008.05.18
Размер файла в сети





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский