|
Hallo Paul and all others,
you know what tool I was looking for when I stumbled over your SPGen tool?
I need a tool where I input two connection strings (one for my productive database and one for my development database): the tool then should give me all the differences between the two databases: which tables have changed with what fields, which stored procedures have been changed/inserted/deleted and so on.
This would be enough but if the tool then also can make the slave database identical to the master, then it would be priceless
Some of you has done anything like that or know of such available tools?
Regards
Stamen
|
|
|
|
|
There are tools out there that do this though I have never bought one as they are pricey.
Adept
Apex
The hardest part is not synching the structures but synching the data. Be very careful as you may loose data, relationships and all sorts.
regards,
Paul Watson
Bluegrass
South Africa
Christopher Duncan quoted:
"...that would require my explaining Einstein's Fear of Relatives"
Crikey! ain't life grand?
Einstein says...
|
|
|
|
|
Thank you Paul,
I actually need a free one
When I synch data, I just backup the master table and then restore it into the slave..
|
|
|
|
|
www.red-gate.com Has a pretty nice, inexpensive tool that does this and more. I've used it in the past and have had some pretty nice results.
|
|
|
|
|
Stamen,
I think you can do this with Visio. I know you can reverse engineer a database using Visio and then compare any changes in the Visio version with the source DB. You can do something like the following:
1) Reverse engineer the production DB into Visio.
2) Change the DB that Visio compares with to the development DB.
3) Synchronize any differences.
Good luck!
|
|
|
|
|
As I did not have time to put this code under scrutiny, this is on top of my head and I believe it is worth considering.
Run this code on a test database in your SQL server:
CREATE TABLE test (iID int IDENTITY(1,1), ntxtField ntext)
After that run the SQL server wizard to create the UPDATE storeed procedure. It will fail, saying something like:
Error 306: The text, ntext and image data types can not be compared or sorted, except when using is NULL or LIKE operator.
The generated code will be like this:
USE [test_db]<br />
GO<br />
CREATE PROCEDURE [update_test_1]<br />
(@iID_1 [int],<br />
@ntxtField_2 [ntext],<br />
@iID_3 [int],<br />
@ntxtField_4 [ntext])<br />
<br />
AS UPDATE [test_db].[dbo].[test] <br />
<br />
SET [iID] = @iID_3,<br />
[ntxtField] = @ntxtField_4 <br />
<br />
WHERE <br />
( [iID] = @iID_1 AND<br />
[ntxtField] = @ntxtField_2)
This is, od course, totally wrong. It is a bit tricky updating ntext fields, as you need to use pointers and WRITETEXT (to alter the whole field), and it should look like this:
... PROCEDURE DECLARATION GOES HERE ...<br />
DECLARE @ptrVal binary(16)<br />
SELECT @ptrVal = TEXTPTR(ntxtField) FROM test WHERE test.iID = @iID<br />
WRITETEXT test.ntxtField @ptrVal @ntxtField
Even though Paul's application will also generate the code that will not work, it can be recoded to work properly.
And this is the benefit of this code in comparison to the SQL server wizard, you can change it as you have a full control over it.
Happy coding.
Sarajevo, Bosnia
|
|
|
|
|
That's funny, I just have spent 6 hours yesterday to work on something similar.
For myself, I decided to stay inside of the SQL-Server and just build a SQL-code generator and also to have a unique SP for all the 3 kinds of action (Insert-Update-Delete).
Since my code is a bit long (actually 261 lines) and use some "advanced" technics (auto-order of tables, using of FSO inside of the SQL, auto-call of osql.exe, etc.) I guess it will go in a full article if somebody is interested.
Currently, it's done this way:
set nocount on
-- We verify that the tables, in which we will store the list of the objects to dynamically create, exist
if not exists (select * from dbo.sysobjects where id = object_id(N'dbo.#TableGenSP') and OBJECTPROPERTY(id, N'IsTable') = 1)
begin
create table #TableGenSP (
tbl_order int identity (1000, 100),
tbl_name sysname not null,
tbl_id int not null
);
create table #TempOrder (
ftbl int not null,
rtbl int not null,
rorder int null
);
end
else
begin
truncate table #TableGenSP
truncate table #TempOrder
end
-- Then we add the temp-procedure specific to keep user-modified statements (inside specific tags)
if exists (select * from dbo.sysobjects where id = object_id(N'dbo.#usp_SaveUserCode') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure #usp_SaveUserCode
go
create procedure #usp_SaveUserCode (@FileID int, @mark varchar(128), @tabcount tinyint = 1)
as
declare @start varchar(256)
declare @end varchar(256)
declare @tab char
declare @temp varchar(1024)
declare @command varchar(4000)
declare @found tinyint
declare @written tinyint
DECLARE @OLEResult INT
DECLARE cursSP CURSOR READ_ONLY FOR SELECT TMPSP_TEXT FROM #TEMPSP ORDER BY TMPSP_ID
select @tab = char(9)
select @start = '--' + @mark + ' START'
select @end = '--' + @mark + ' END'
select @found = 0
select @written = 0
open cursSP
fetch next from cursSP into @temp
while @@fetch_status = 0
begin
if patindex ('%' + @start + '%', @temp) <> 0
begin
select @found = 1
select @temp = replace (replace (@temp , char(13), '') , char(10), '')
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @temp
select @written = 1
end
else if patindex ('%' + @end + '%', @temp) <> 0
begin
select @found = 0
select @temp = replace (replace (@temp , char(13), '') , char(10), '')
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @temp
select @written = 2
end
else
begin
if @found = 1
begin
select @temp = replace (replace (@temp , char(13), '') , char(10), '')
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @temp
end
end
fetch next from cursSP into @temp
end
close cursSP
deallocate cursSP
if @written = 0
begin
select @temp = replicate (@tab, @tabcount) + @start
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @temp
end
if @written <> 2
begin
select @temp = replicate (@tab, @tabcount) + @end
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @temp
end
go
-- We insert first all the objects which are not referencing something else using a foreign key
insert into #TableGenSP (tbl_name, tbl_id)
select name, id
from sysobjects
where xtype = 'U' and name not in ('dtproperties', 'TableGenSp', 'TempOrder') and id not in (select parent_obj from sysobjects where xtype = 'F')
-- We insert then all the foreign references
insert into #TempOrder (ftbl, rtbl)
select fkeyid, rkeyid from sysreferences
where fkeyid in (
select parent_obj from sysobjects where xtype = 'F' and parent_obj in (select fkeyid from sysreferences)
and parent_obj not in (select tbl_id from #TableGenSP))
-- Now we have to update our two tables by using an update process ::
-- We are adding tables as long as their foreign dependencies can be resolved.
-- This is possible if the datamodel is well built (ie. no circular dependencies between tables)
while exists (select * from #TempOrder where rorder is null)
begin
update #TempOrder set rorder = tbl_order from #TableGenSP inner join #TempOrder on rtbl = tbl_id and rorder is null
insert into #TableGenSP (tbl_name, tbl_id)
select name, id from sysobjects
where id in (select ftbl from #TempOrder where ftbl not in (select distinct ftbl from #TempOrder where rorder is null))
and id not in (select tbl_id from #TableGenSP)
end
declare @tempdir varchar(260)
declare @fname varchar(260)
declare @spname sysname
declare @svrname sysname
declare @dbosql sysname
declare @imp_user sysname
declare @table sysname
declare @name sysname
declare @col sysname
declare @xtype int
declare @coltype sysname
declare @length int
declare @id numeric
declare @SelKey varchar(2048)
declare @command varchar(4000)
declare @var varchar(255)
declare @cols varchar(4000)
declare @vars varchar(4000)
declare @crlf varchar(2)
declare @tab char
declare @first tinyint
DECLARE @FS INT, @OLEResult INT, @FileID INT
declare cursTable cursor read_only for select tbl_name, tbl_id from #TableGenSP order by tbl_order
select @tempdir = 'f:\temp'
select @svrname = 'arcturus'
select @dbosql = 'fineurope'
select @imp_user = 'fineurope'
select @crlf = char(13) + char(10)
select @tab = char(9)
EXECUTE @OLEResult = sp_OACreate 'Scripting.FileSystemObject', @FS OUT
IF @OLEResult <> 0 PRINT 'Scripting.FileSystemObject'
open cursTable
fetch next from cursTable into @table, @id
while @@fetch_status = 0
begin
select @spname = 'usp_' + @table
select @fname = @tempdir + '\' + @spname + '.sql'
CREATE TABLE #TEMPSP (TMPSP_ID int IDENTITY, TMPSP_TEXT varchar(1024))
INSERT INTO #TEMPSP EXEC sp_helptext @SPNAME
EXECUTE @OLEResult = sp_OAMethod @FS, 'OpenTextFile', @FileID OUT, @fname, 2, 1
IF @OLEResult <> 0 PRINT 'OpenTextFile'
select @command = 'if exists (select * from dbo.sysobjects where id = object_id(N''dbo.' + @spname + ''') and OBJECTPROPERTY(id, N''IsProcedure'') = 1)' + @CRLF
select @command = @command + 'drop procedure dbo.' + @spname + @crlf
exec (@command)
select @command = 'CREATE PROCEDURE dbo.' + @spname + '(@action char'
select @vars = ''
declare cursCols cursor read_only for
select sc.name, sc.xtype, st.name, sc.length from syscolumns sc
inner join systypes st on sc.xusertype = st.xusertype
where id = @id and sc.xusertype not in (34, 35, 99)
-- We are adding this, since with our conventions column's name containing
-- DATECREATED or LASTUPDATE have values only from DEFAULT or trigger
and patindex ('%datecreated', sc.name) = 0 and patindex ('%lastupdate', sc.name) = 0
order by colid
open cursCols
fetch next from cursCols into @col, @xtype, @coltype, @length
while @@fetch_status = 0
begin
select @col = replace (@col, ' ', '_')
select @var = @col + ' ' + @coltype
if @xtype in (167, 175)
begin
select @var = @var + '(' + convert (varchar(16), @length) + ')'
end
-- We must deal with tne N types differently
else if @xtype in (231, 239)
begin
select @var = @var + '(' + convert (varchar(16), @length / 2) + ')'
end
select @command = @command + ', @' + @var + ' = null'
select @vars = @vars + @tab + 'declare @old_' + @var + @crlf
fetch next from cursCols into @col, @xtype, @coltype, @length
end
close cursCols
deallocate cursCols
select @command = @command + ')' + @crlf
select @command = @command + 'as' + @crlf
select @command = @command + @tab + 'set nocount on' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = @vars
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = ''
-- First We build the WHERE clause for all requests
select @first = 1
select @SelKey = ''
declare cursKey cursor read_only for select name from syscolumns sc inner join
(select sik.id, sik.colid from sysindexkeys sik inner join sysindexes six on sik.id = six.id and sik.indid = six.indid
inner join sysobjects so on six.name = so.name and so.xtype = 'PK' and six.id = @id) t
on sc.id = t.id and sc.colid = t.colid
open cursKey
fetch next from cursKey into @name
while @@fetch_status = 0
begin
if @first = 0
begin
select @SelKey = @SelKey + ' AND '
end
select @first = 0
select @SelKey = @SelKey + '[' + @name + '] = @' + replace (@name, ' ', '_')
fetch next from cursKey into @name
end
close cursKey
deallocate cursKey
exec #usp_SaveUserCode @FileID, 'EnterSP', 1
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, ''
-- First action is DELETE
select @command = @tab + 'if @action = ''D''' + @crlf
select @command = @command + @tab + 'begin'
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'Before DELETE', 1
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, ''
select @command = @tab + @tab + 'DELETE FROM [' + @table + '] WHERE ' + @SelKey + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'After DELETE', 2
select @command = @tab + 'end'
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = @tab + 'else if @action = ''U''' + @crlf
select @command = @command + @tab + 'begin' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'Before UPDATE', 2
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, ''
select @command = @tab + @tab + 'UPDATE [' + @table + '] SET'
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = ''
select @cols = ''
select @first = 1
declare cursCols cursor read_only for
select sc.name from syscolumns sc
inner join systypes st on sc.xtype = st.xtype
where id = @id and sc.autoval is null and sc.xtype not in (34, 35, 99)
-- We are adding this, since with our conventions column's name containing
-- DATECREATED or LASTUPDATE have values only from DEFAULT or trigger
and patindex ('%datecreated', sc.name) = 0 and patindex ('%lastupdate', sc.name) = 0
order by colid
open cursCols
fetch next from cursCols into @col
while @@fetch_status = 0
begin
select @command = @command + @tab + @tab + @tab
if @first = 0
begin
select @command = @command + ', '
end
select @first = 0
select @command = @command + '[' + @col + '] = @' + replace (@col, ' ', '_') + @crlf
fetch next from cursCols into @col
end
close cursCols
deallocate cursCols
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = @tab + @tab + 'WHERE ' + @SelKey + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'After UPDATE', 2
select @command = @tab + 'end'
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
-- Then the INSERT
select @command = @tab + 'else if @action = ''I''' + @crlf
select @command = @command + @tab + 'begin'
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = ''
select @cols = ''
select @vars = ''
select @first = 1
declare cursCols cursor read_only for
select sc.name from syscolumns sc
inner join systypes st on sc.xtype = st.xtype
where id = @id and sc.autoval is null and sc.xtype not in (34, 35, 99)
-- We are adding this, since with our conventions column's name containing
-- DATECREATED or LASTUPDATE have values only from DEFAULT or trigger
and patindex ('%datecreated', sc.name) = 0 and patindex ('%lastupdate', sc.name) = 0
order by colid
open cursCols
fetch next from cursCols into @col
while @@fetch_status = 0
begin
if @first = 0
begin
select @cols = @cols + ', '
select @vars = @vars + ', '
end
select @first = 0
select @cols = @cols + '[' + @col + ']'
select @vars = @vars + '@' + replace (@col, ' ', '_')
fetch next from cursCols into @col
end
close cursCols
deallocate cursCols
exec #usp_SaveUserCode @FileID, 'Before INSERT', 2
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, ''
select @command = @tab + @tab + 'INSERT INTO [' + @table + ']' + @crlf
select @command = @command + @tab + @tab + @tab + '(' + @cols + ')' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
select @command = @tab + @tab + 'VALUES' + @crlf
select @command = @command + @tab + @tab + @tab + '(' + @vars + ')' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'After INSERT', 2
select @command = @tab + 'end' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
exec #usp_SaveUserCode @FileID, 'ExitSP', 1
select @command = 'go' + @crlf
EXECUTE @OLEResult = sp_OAMethod @FileID, 'WriteLine', NULL, @command
EXECUTE @OLEResult = sp_OADestroy @FileID
SELECT @command = 'osql.exe -S' + @SVRNAME + ' -U' + @IMP_USER + ' -P' + @IMP_USER + ' -d' + @DBOSQL + ' -i' + @FNAME + ' -n'
EXEC master..xp_cmdshell @command
if not exists (select * from dbo.sysobjects where id = object_id(N'dbo.' + @SPNAME) and OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
print 'Error creating : ' + @spname
END
ELSE
BEGIN
EXECUTE @OLEResult = sp_OAMethod @FS, 'DeleteFile', NULL, @FNAME, -1
IF @OLEResult <> 0 PRINT 'WriteLine : DeleteFile ' + @FNAME + ' error ' + convert (varchar(32), @OleResult)
END
fetch next from cursTable into @table, @id
DROP TABLE #TEMPSP
end
close cursTable
deallocate cursTable
-- Our job is over, we can clean everything
EXECUTE @OLEResult = sp_OADestroy @FS
drop table #TableGenSP
drop table #TempOrder
drop procedure #usp_SaveUserCode
This can be enhanced a little,by adding error-check code for example.
Eric
|
|
|
|
|
Eric Lapouge wrote:
For myself, I decided to stay inside of the SQL-Server and just build a SQL-code generator and also to have a unique SP for all the 3 kinds of action (Insert-Update-Delete).
Wow, first off thanks for all that code. That is way beyond my TSQL skills, but I will dig in and try my best
Also staying within SQL Server Enterprise Manager was my original intent too. What I really wanted to do was simply add a new option to the context menu when you right click a Table in SSEM. It would have made things a lot easier and more powerful as then people would have all the capabilities of SSEM but with just the added SP generator code.
I did not dig too hard, but how do you create add-ins/extensions for SSEM?
Paul Watson Bluegrass Cape Town, South Africa Shog9 wrote:
Everybody just wants to be naked and famous, Paul.
|
|
|
|
|
Hi,
If you have some questions, don't hesitate to ask...
It's a bit off topic for the board, but we can work together to add : my generator, to your app. If Interested, just mail.
I'm going to do some researches on the functionnality you asked for.
Regards,
Eric
|
|
|
|
|
|
Thomas George wrote:
If you could put the field/table names in [ ],
Good idea Thomas, thanks.
Paul Watson Bluegrass Cape Town, South Africa Shog9 wrote:
Everybody just wants to be naked and famous, Paul.
|
|
|
|
|
this functionality is built into the sql query analyzer, on the object browser right click a table, then choose script to new window > insert
-j
|
|
|
|
|
Where is it built-in? What you are talking about creates an insert statement, nothing more. His app creates a full-fledged stored procedure with all the parameters defined for you.
|
|
|
|
|
mikelb wrote:
app creates a full-fledged stored procedure with all the parameters defined for you.
Thanks for the backup mikelb.
Paul Watson Bluegrass Cape Town, South Africa NOPcode wrote:
...but in America, you're not allowed to thrust, moan or see anything...
|
|
|
|
|
jwelty wrote:
this functionality is built into the sql query analyzer, on the object browser right click a table, then choose script to new window > insert
Awesome, I had not noticed that functionality in SQL Query Analyzer before. Thanks for pointing that out
However my little app does go a bit further in that instead of just creating the UPDATE or INSERT statement it also defines the parametres and feeds them into the UPDATE or INSERT statement.
Seeing as QA has the functionality you pointed out I wonder if I can tap into it and use the statement generation instead of my horrendous string manipulations. Then I can just append my parametre declaration and put in the rest of the SP notation.
I am so used to the old QA (with SQL 7.0) that I hardly ever use the raft of new features in the SQL 2000 QA.
Paul Watson Bluegrass Cape Town, South Africa NOPcode wrote:
...but in America, you're not allowed to thrust, moan or see anything...
|
|
|
|
|
Hi Paul
While looking at the source I realized I could not set breakpoints while debugging. This (after some fishing) is due to an improperly configured sln file. Content:
GlobalSection(ProjectConfiguration) = postSolution
{87ADD9EE-AA83-45B8-9BD8-4EC5FC26CCAB}.Debug.ActiveCfg = Release|.NET
{87ADD9EE-AA83-45B8-9BD8-4EC5FC26CCAB}.Debug.Build.0 = Release|.NET
{87ADD9EE-AA83-45B8-9BD8-4EC5FC26CCAB}.Release.ActiveCfg = Release|.NET
{87ADD9EE-AA83-45B8-9BD8-4EC5FC26CCAB}.Release.Build.0 = Release|.NET
As you can see all configs point to a release build, and thus cannot build debug builds. Not sure why this would have happened to you!
DBHelper - SQL Stored Procedure Wrapper & Typed DataSet Generator for .NET
|
|
|
|
|
leppie wrote:
As you can see all configs point to a release build, and thus cannot build debug builds. Not sure why this would have happened to you
Woah that is weird. As requested by CP I always do a Release build for the files I upload, but the debug option should still be there.
I just checked in VS.NET and Debug is still an option for the build config.
leppie wrote:
While looking at the source I realized I could not set breakpoints while debugging
You actually looked at the source? You poor bugger...
Paul Watson Bluegrass Cape Town, South Africa Christopher Duncan wrote:
Which explains why when Santa asked, "And what do you want for Christmas, little boy?" I said, "A life." (Accesories sold separately)
|
|
|
|
|
|
leppie wrote:
Look what I found today http://www.sd.nl/software[^]. Pretty nice
Cool, that thing does everything. Going to go see if I can get the source to see how they did it all.
thanks
Paul Watson Bluegrass Cape Town, South Africa Christopher Duncan wrote:
Which explains why when Santa asked, "And what do you want for Christmas, little boy?" I said, "A life." (Accesories sold separately)
|
|
|
|
|
Oh please, not that dreaded pro/con dataset debate! :P
I received your code leppie, thanks for that. The reason I haven't included dataSET support is that the select procedures return a single set, thus a dataTABLE is more than enough. A full dataset is then a bit overkill. True, a typed dataset can be helpful, but a typed dataset is nothing more than a generated class derived from dataset itself, imho not that helpful in a stateLESS environment.
Nice tool, paul, especially for 45minutes of coding
|
|
|
|
|
Small world Is there anyone not on CP?
Frans Bouma wrote:
True, a typed dataset can be helpful, but a typed dataset is nothing more than a generated class derived from dataset itself, imho not that helpful in a stateLESS environment.
What do mean by not being helpful? I realise things like generated events might not be of use, but just having it typed, I feel, is more than helpful, even just not having to cast everytime you access a Row.
Frans Bouma wrote:
Oh please, not that dreaded pro/con dataset debate!
Any links that can enlighten me?
Frans Bouma wrote:
I received your code leppie, thanks for that.
I had a look at your code, and was wondering why you didnt use CodeDom to generate C#/VB.NET code?
Cheers
DBHelper - SQL Stored Procedure Wrapper & Typed DataSet Generator for .NET
|
|
|
|
|
leppie wrote
What do mean by not being helpful? I realise things like generated events might not be of use, but just having it typed, I feel, is more than helpful, even just not having to cast everytime you access a Row.
The problem is: when you use a typed dataset, you end up doing datamanipulation in the dataset, or at least you offer that functionality, which is plain wrong in an n-tier stateless environment. Most of the time people end up using their own objects based on a class in System.Collections and store their data in there, read from the datatables. True, these code has to be written by hand, but its way more efficient. I'd rather use a customers collection which will load dynamically a customer record from the database when I do:
<br />
MyCustomerClass oCustomer = Customers.Customer(iIDOfCustomer);<br />
But it's a matter of choice I think. DataSets IMHO are ment to be used in stateful environments where you read data from the database into a dataset, manipulate it in that dataset and then populate the data back to the database using the dataset's methods. To me there doesn't seem any advantage for using a dataset in an n-tier stateless environment (the same goes for the datareader object, which is not useable in an n-tier stack because passing it to other tiers will move an open database connection over tier boundaries, resulting in the distruction of abstractioness introduced with the n-tier model in the first place!
leppie wrote
Any links that can enlighten me?
Search for 'LLBLGen' in the www.asp.net forums, you'll end up with a lot of debate surrounding datatables and datasets, statefull/less etc. I wrote a page about n-tier stateless development in the LLBLGen documentation which illustrates my view on the matter. Other views may/will differ of course however.
leppie wrote
I had a look at your code, and was wondering why you didnt use CodeDom to generate C#/VB.NET code?
As a matter of fact, I released version 1.0 and 3 days later I found out about that namespace! . Back then it was C# only so I looked into it to port the code over to codedom code so I could easily port it to VB.NET but it's very cumbersome to write emittercode for codedom. The converters I've seen who eat C# code and generate codedom targetting code all state that not all code constructions are portable to codedom statements.
I've decided to move to templates for v2.0, which are way easier to maintain.
--
Only the true wise understand the difference between knowledge and wisdom.
|
|
|
|
|
Frans Bouma wrote:
I wrote a page about n-tier stateless development in the LLBLGen documentation which illustrates my view on the matter
Will have a read
Frans Bouma wrote:
As a matter of fact, I released version 1.0 and 3 days later I found out about that namespace!
Dont you hate it when that happens? Especially that missed static method, only to find out it does the same as your next 100 lines
I do find coding the CodeDom is a bit painfull and I havent seen any worthwhile parsers, but it makes code generation much more bug free (especially since I dont know VB.NET ).
Frans Bouma wrote:
I've decided to move to templates for v2.0, which are way easier to maintain.
Sounds interesting
Cheers
DBHelper - SQL Stored Procedure Wrapper & Typed DataSet Generator for .NET
|
|
|
|
|
Frans Bouma wrote:
Nice tool, paul, especially for 45minutes of coding
Thanks Frans.
The proper article, with nicer code, is about ready to be posted.
Paul Watson Bluegrass Cape Town, South Africa NOPcode wrote:
...but in America, you're not allowed to thrust, moan or see anything...
|
|
|
|
|
Very cool! Downloading.... I'm looking forward to seeing the code. Do you have any objections to it being built onto?
I knew it would end badly when I first met Chris in a Canberra alleyway and he said 'try some - it won't hurt you'..... - Christian Graus on Code Project outages
Damned nice for remote servers where using Enterprise Manager is like wadding through treacle while covered in velcro, upside down -Paul Watson on SQL Server Query Analyser
|
|
|
|
|