1

Konu: VFP tabloları ve SQL Server icin NewID ve GetNextID

VfpOledb uyumlu VFP Tabloları ve SQL Server icin NewID ve GetNextID cozumu nasil olabilir ?

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

2

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

IDS tablosu:
tablename, c(20) && 20 bana yetiyor daha buyuk olabilir tabii.
nextid i

-tablename alani indexli


Database SP:

Visual Fox Pro
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Function NewID

    Lparameters tcAlias,tnCount
    Local lcAlias, lnOldArea, lcOldReprocess, lcTable, lnTagNo, lnNewValue, lnLastValue, lcOldSetDeleted
    lnOldArea = Select()
    lnOldReprocess = Set('REPROCESS')
    * Uppercase Alias name
    lcAlias = Upper(Iif(Parameters() = 0, Alias(), tcAlias))
    * Lock reprocess - try once
    Set Reprocess To 1
    If !Used("IDS")
        Use ids In 0
    Endif
    * If no entry yet create
    If !Seek(lcAlias, "Ids", "tablename")
        Insert Into ids (tablename, NextID) Values (lcAlias,0)
    Endif
    * Lock, increment id, unlock, return nextid value
    Do While !Rlock('ids')
        * Delay before next lock trial
        lnStart = Seconds()
        Do While Seconds()-lnStart < 0.01
        Enddo
    Enddo
 
    lnLastValue = ids.NextID
    lnNewValue  = m.lnLastValue + Evl(m.tnCount,1)
 
    *Try to query primary key tag for lcAlias
    lcTable = Iif( Used(lcAlias),Dbf(lcAlias), Iif(File(lcAlias+'.dbf'),lcAlias,''))
    lcTable = Evl(m.lcTable,m.lcAlias)
    If !Empty(lcTable)
        Use (lcTable) In 0 Again Alias '_GetPKKey_'
        For m.lnTagNo=1 To Tagcount('','_GetPKKey_')
            If Primary(m.lnTagNo,'_GetPKKey_')
                m.lcOldSetDeleted = Set("Deleted")
                Set Deleted Off
 
                Select '_GetPKKey_'
                Set Order To Tag (Tag(m.lnTagNo,'_GetPKKey_')) ;
                    In '_GetPKKey_' Descending
                Locate
                lnLastValue = Max(m.lnLastValue, Evaluate(Key(m.lnTagNo,'_GetPKKey_')))
                lnNewValue = m.lnLastValue + Evl(m.tnCount,1)
 
                If Upper(m.lcOldSetDeleted) == 'ON'
                    Set Deleted On
                Endif
                Exit
            Endif
 
        Endfor
        Use In '_GetPKKey_'
        Select ids
    Endif
 
    * Increment
    Replace ids.NextID With m.lnNewValue In 'ids'
    Unlock In 'ids'
    Select (lnOldArea)
    Set Reprocess To lnOldReprocess
    Return ids.NextID
Endfunc

SQL server NextID:

SQL
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- Procedure NextID

CREATE procedure [dbo].[NextId]
    @tableName varchar(200), @start int output, @end int output, @nRows int = 1
AS
begin
    SET nocount ON
    UPDATE ids SET nextID = nextID + @nRows WHERE tableName = upper(@tableName);
    IF @@rowcount = 0
        begin
        INSERT INTO ids (tableName,nextID) VALUES (upper(@tableName),@nRows);
        end
 
    SELECT @start = nextID -@nRows + 1,@end = nextID FROM ids WHERE tableName = @tableName;
--nextId is last ID used
--nRows IDs are allocated for the caller
end

Runtime'da ID almak icin:

*GetNextID.prg

Visual Fox Pro
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Lparameters tcTableName, tnCount

IF VARTYPE(oApp)!='O' AND VARTYPE(_screen.oApp) = 'O'
    oApp = _screen.oApp
endif
 
Local loConn as 'ADODB.Connection',loCommand as 'ADODb.Command',loRS as 'ADODb.RecordSet',lnReturn
loConn = Createobject('ADODB.Connection')
loCommand = Createobject('ADODB.Command')
loConn.ConnectionString = oApp.ADODataConnectionString
loConn.Open
loCommand.ActiveConnection = loConn
loCommand.CommandType = 4 && stored procedure
Do Case
    Case oApp.DataMode == 'SQL'
        loCommand.CommandText = 'NextID'
        loCommand.Parameters.Refresh
        loCommand.Parameters('@tableName').Value = m.tcTableName
        loCommand.Parameters('@nRows').Value = EVL(m.tnCount,1)
        loCommand.Execute
        lnReturn = loCommand.Parameters('@end').Value
    Case oApp.DataMode == 'VFP'
        loCommand.CommandText = Textmerge('NewID("<<m.tcTableName>>",<<EVL(m.tnCount,1)>>)')
        loRS = loCommand.Execute
        lnReturn = loRS.Fields(0).Value
        loRS.Close
Endcase
loConn.Close
Return m.lnReturn
Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

3

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

Kullanimi:

Visual Fox Pro
1

id = GetNextID( "Customer" ) && Customer tablosu icin ID al

Visual Fox Pro
1

idLast = GetNextID( "Customer", 10 ) && Customer tablosu icin 10 ID rezerve et sonunucuyu al - gerisi basit aritmetik
Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

4

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

Teşekkürler,
VFP kısmı zaten calisiyordu
SQL tablolari icinde tabloları yaratan scriptte ilgili kolonun default una GetNextID( "TableName" ) yazmamiz yeterli olacak sanirim
tablolar ile birlikte NextID SP de onceden yaratilmis oldugu icinde SQL tarafinda aradigini bulacaktir dogrumudur hocam ?

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

5

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

evet

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

6

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

NewID()  da asagidaki kısım PrimaryKey olan ve GUID alan tablolarda Operant Type Mismatch hatasi veriyor bu kısmı Remarklarsam sorun yok yada ilgili alanın Index ini Regular yaparsam .

Bununla ilgili ne onerirsin hocam ? Regular a ceksem GUID degeri alan bir kaydin tekrari herhalde denk gelmez sad
remarklarsam VFPOLEDB nin Set Delete Off/on la ilgili bir hassasiyeti var zaten kod icinde de geciyor .

Visual Fox Pro
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
*Try to query primary key tag for lcAlias

    lcTable = Iif( Used(lcAlias),Dbf(lcAlias), Iif(File(lcAlias+'.dbf'),lcAlias,''))
    lcTable = Evl(m.lcTable,m.lcAlias)
    If !Empty(lcTable)
        Use (lcTable) In 0 Again Alias '_GetPKKey_'
        For m.lnTagNo=1 To Tagcount('','_GetPKKey_')
            If Primary(m.lnTagNo,'_GetPKKey_')
                m.lcOldSetDeleted = Set("Deleted")
                Set Deleted Off
 
                Select '_GetPKKey_'
                Set Order To Tag (Tag(m.lnTagNo,'_GetPKKey_')) ;
                    In '_GetPKKey_' Descending
                Locate
                lnLastValue = Max(m.lnLastValue, Evaluate(Key(m.lnTagNo,'_GetPKKey_')))
                lnNewValue = m.lnLastValue + Evl(m.tnCount,1)
 
                If Upper(m.lcOldSetDeleted) == 'ON'
                    Set Deleted On
                Endif
                Exit
            Endif
 
        Endfor
        Use In '_GetPKKey_'
        Select ids
    Endif
http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

7

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

Ya Soykan,
Bu zaten sadece int keyler icin. Madem GUID kullaniyorsun neden SP gereksin ki.

* UniqueID.prg

Visual Fox Pro
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Lparameters tl38

Local pGUID,rGUID
Declare Integer UuidCreate In 'RPCRT4.dll' String @pguid
Declare Integer StringFromGUID2 In 'Ole32.dll' ;
  string rguid, String @lpsz, Integer cchMax
 
pGUID=Replicate(Chr(0),16)
rGUID=Replicate(Chr(0),80)
 
UuidCreate(@pGUID)
StringFromGUID2(pGUID,@rGUID,40)
If m.tl38
  Return Strconv(Left(rGUID,76),6)
Else
  Return Chrtran(Strconv(Left(rGUID,76),6),'{}','')
Endif
Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

8

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

VFP de GUID i default undan aldirmak icin SP kullaniyorum o yuzden smile

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

9

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

tablolun defaultuna GetNextID( "TableName" ) yazamiyorum SQL Server R2 kabul etmiyor sad daha doğrusu kendisinin Build in Function i olmadigi icin dogal olarak...

onceden ID alip insert into ile siranosunu vermek gerekecek

asagidaki kodlarla ID almak icin bir deneme yaptim ama olmadi sad Invalid Object Name IDS diyor halbuki IDS tablosuda NextID SP de Database de mevcut

Visual Fox Pro
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
PUBLIC oApp

LOCAL lcDB,lcServer
m.lcDB = 'depomatik'
m.lcServer = '.\sqlExpress'
 
oApp=Createobject("MyApp")
 
WAIT WINDOW  getnextID('arizatb')
 
Define Class MyApp As Custom
    datamode = 'SQL'
    ADODataConnectionString = 'Provider=SQLNCLI10;server=' + m.lcServer + ';Trusted_Connection=yes;Database=' + m.lcDB
    DataConnectionString = 'Provider=SQLNCLI10;server=' + m.lcServer + ';Trusted_Connection=yes;Database=' + m.lcDB
Enddefine
 
Function GetNextID
    Lparameters tcTableName, tnCount
    If Vartype(oApp)!='O' And Vartype(_Screen.oApp) = 'O'
        oApp = _Screen.oApp
    Endif
 
    Local loConn As 'ADODB.Connection',loCommand As 'ADODb.Command',loRS As 'ADODb.RecordSet',lnReturn
    loConn = Createobject('ADODB.Connection')
    loCommand = Createobject('ADODB.Command')
    loConn.ConnectionString = oApp.ADODataConnectionString
    loConn.Open
    loCommand.ActiveConnection = loConn
    loCommand.CommandType = 4 && stored procedure
    Do Case
        Case oApp.datamode == 'SQL'
            loCommand.CommandText = 'NextID'
            loCommand.Parameters.Refresh
            loCommand.Parameters('@tableName').Value = m.tcTableName
            loCommand.Parameters('@nRows').Value = Evl(m.tnCount,1)
            loCommand.Execute
            lnReturn = loCommand.Parameters('@end').Value
        Case oApp.datamode == 'VFP'
            loCommand.CommandText = Textmerge('NewID("<<m.tcTableName>>",<<EVL(m.tnCount,1)>>)')
            loRS = loCommand.Execute
            lnReturn = loRS.Fields(0).Value
            loRS.Close
    Endcase
    loConn.Close
    Return m.lnReturn
Endfunc
 
 
  Procedure GetErrorExplanation
    Local lcError,ix
    Local Array aWhy[1]
    Aerror(aWhy)
    lcError = ""
    For ix = 1 To 7
      lcError = m.lcError + Transform(aWhy[m.ix]) + Chr(13)
    Endfor
    Return m.lcError
  Endproc
http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

10

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

SQL serverda SPleri default olarak kullanamiyorsun. Ben triggerlar ile yapmisitim (o sqlservertransfer kodu yaratiyor bu kodlari) - soyle birsey:


SQL
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-- Insert trigger for MyTable

CREATE TRIGGER [dbo].[Trig_Insert_MyTable] ON [dbo].[MyTable]
    instead of INSERT
AS
begin
    SET nocount ON
    declare @keysRequired int, @current int
    SELECT @keysRequired = Count(*) FROM inserted WHERE isnull([REC_ID],0) = 0;
    IF @keysRequired > 0
        begin
            declare @keyStart int, @keyEnd int
            exec NextId 'MyTable', @keyStart output,@keyEnd output, @keysRequired
            SET @current = @keyStart-1
            IF EXISTS
              (SELECT * FROM tempdb.sys.objects WHERE object_id = OBJECT_ID(N'[tempdb]..[#inserted]','U'))
                     DROP TABLE #inserted;
 
            SELECT * INTO #inserted from inserted;
            UPDATE #inserted
               SET @current=@current+1, [PKID] = @current
               WHERE isnull([PKID],0) = 0;
            INSERT INTO [MyTable]
            ([pkid], ... )
            SELECT
            [pkid], ...
            FROM #inserted;
            DROP TABLE #inserted;
        end
    else
        begin
            INSERT INTO [MyTable]
            ([pkid], ...)
            SELECT
            [pkid], ...
            FROM inserted;
        end
end
-- Insert trigger for MyTable
Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

11

Re: VFP tabloları ve SQL Server icin NewID ve GetNextID

bu durumda asagidaki Trigger olsuturma kodu ile ID gereken tablolar icin Trigger Olusturmam gerekiyor smile Hatta olusturdum islem tamamdir tesekkurler.

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg