Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 General SQL Server Forums
 New to SQL Server Programming
 C# SMO generated functioncreate script problem

Author  Topic 

baro1
Starting Member

6 Posts

Posted - 2011-07-20 : 06:52:19
Hello,
I am creating a create script on C# using SMO. (see the code below)
The functions I'm scripting are dependent on each other, I mean there are call from one to other one on some places.

The problem shows up when I run the created script. Because the functions are dependent on each other, they have to be created in RIGHT ORDER, otherwise, as in my situation, I'm getting errors when executing the script, a function lack of a function which is going to be created a few steps later.

I have a cunning plan though, - putting a number prefix on functions so they would be created in right order - not accepted as a feasible solution.


foreach (UserDefinedFunction udf in db.UserDefinedFunctions)
{
if (!udf.IsSystemObject)
foreach (var v in udf.Script())
sb.Append(v + "\nGO\n");
}

mohdowais
Sheikh of Yak Knowledge

1456 Posts

Posted - 2011-07-20 : 07:30:55
A couple of slightly less cunning ways would be:

1. Keep track of how many function declarations failed and re-run the CREATE statements until you get no errors
2. Use the brilliant dm_sql_referenced_entities function to identify which other objects this particular function depends on. You could perhaps store a list of all previously created objects in a hashtable and if any of the objects that are required by this function are not yet created, you could either create them first or defer creation of this function until they are ready.

OS
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-07-20 : 07:35:08
If you are trying to create dependent objects in the right order, perhaps you could write a C# function that would:

1. Walk through the list of functions that you want to create
2. For each function invoke one of the SQL DMVs or functions to find its dependencies
3. Invoke the function recursively for the dependent objects

Here is a description of the functions/DMVs that will allow you to examine dependencies.

Two disclaimers:

1. I have never tried to do this myself. So my suggestion is theoretical.

2. Not sure what the code fragment you posted is for. So, if I am answering a question you didn't ask, please feel free to ignore

Go to Top of Page

baro1
Starting Member

6 Posts

Posted - 2011-07-20 : 09:52:02
quote:
Originally posted by mohdowais

A couple of slightly less cunning ways would be:

1. Keep track of how many function declarations failed and re-run the CREATE statements until you get no errors
2. Use the brilliant dm_sql_referenced_entities function to identify which other objects this particular function depends on. You could perhaps store a list of all previously created objects in a hashtable and if any of the objects that are required by this function are not yet created, you could either create them first or defer creation of this function until they are ready.

OS



This creating a "create script" is a backup from c# code and I am not good enough on T-SQL to write a programatical implementation of both steps. I was in search of doing this using C# SMO.

sunitabeck's way also needs a T-SQL implementation I guess, or some query executions on the process.

BUT I came up with a dumbass c# solution. I found the dependencies by doing a "contains" check on the create scripts of other functions. I do a check of the first function's name with all other ones' scripts, if it finds a referance of that name, it simply puts that function on the last place of the queue. here's the code. too bad SMO api doesnt have anything helpful on dependencies as I've checked.


StringBuilder sb2 = new StringBuilder();
Queue<string> funcList = new Queue<string>();
Queue<UserDefinedFunction> udfq = new Queue<UserDefinedFunction>();

foreach (UserDefinedFunction udf in db.UserDefinedFunctions)
{
if (!udf.IsSystemObject)
{
foreach (var v in udf.Script())
sb2.Append(v + "\nGO\n");

funcList.Enqueue(sb2.ToString());
sb2 = new StringBuilder();

udfq.Enqueue(udf);
}
}

while(udfq.Count != 0)
{
var flag = false;
var current = udfq.Dequeue();

foreach (var userDefinedFunction in udfq)
if (funcList.Peek().Contains(userDefinedFunction.Name))
{
flag = true;
break;
}

if(!flag)
{
sb.Append(funcList.Dequeue());
}
else
{
funcList.Enqueue(funcList.Dequeue());
udfq.Enqueue(current);
}
}
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-20 : 12:05:48
Since you're scripting EVERY function in the database, who cares what order they get scripted in?

What error are you getting?
Go to Top of Page

baro1
Starting Member

6 Posts

Posted - 2011-07-21 : 03:22:28
lets say we have func1 which calls another function "func2" inside. if I do something like


CREATE FUNCTION func1()
/*some calls here to func2*/
GO

CREATE FUNCTION func2()
/*cleverness here*/
GO



I get errors on CREATE FUNCTION func1 command, as func2 doesnt exist yet. When I do this on SQL Management Studio, I simply right click on db, tasks->generate scripts and it generates the functions in right order. when I iterate the functions on c#, they are not ordered, thus gives me errors
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-21 : 11:07:37
I don't get errors when I do it.

Tested in SQL 2005, 2008, 2008R2.
Go to Top of Page

baro1
Starting Member

6 Posts

Posted - 2011-07-22 : 08:31:19
quote:
Originally posted by russell

I don't get errors when I do it.

Tested in SQL 2005, 2008, 2008R2.



You have to get errors. How would it be possible to have a call to a function which doesnt exist yet?
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-07-22 : 08:47:59
If you are only creating the functions (and not invoking those functions), this is possible. This example should demonstrate what russell said - dbo.F2 does not exist when dbo.F1 is created, even though dbo.F1 refers to dbo.F2:
CREATE FUNCTION dbo.F1(@num INT)
RETURNS INT
BEGIN
RETURN dbo.F2(@num);
END
GO

-- select dbo.F2(1) --<-- this would throw an error
-- GO

CREATE FUNCTION dbo.F2(@num INT)
RETURNS INT
BEGIN
RETURN @num*2;
END
GO

SELECT dbo.F1(1);

DROP FUNCTION dbo.F2, dbo.F1;
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-07-22 : 08:54:37
I want to sort of correct/take back what I said above. If you are creating the functions with schemabinding, you would run into a problem unless the functions are created in order. The code below would not work:

CREATE FUNCTION dbo.F1(@num INT)
RETURNS INT WITH SCHEMABINDING
BEGIN
RETURN dbo.F2(@num);
END
GO

CREATE FUNCTION dbo.F2(@num INT)
RETURNS INT WITH SCHEMABINDING
BEGIN
RETURN @num*2;
END
GO

Go to Top of Page

baro1
Starting Member

6 Posts

Posted - 2011-07-22 : 09:51:16
here let me show my not executing code piece :


CREATE FUNCTION [dbo].[ClinicSchedule](@StartDate datetime,@EndDate datetime)
RETURNS TABLE as
RETURN
SELECT c.dt FROM ClinicOpenDays(@StartDate,@EndDate) as c
WHERE c.dt NOT IN (SELECT Date FROM Holidays)

GO


ClinicOpenDays is also a table-valued function.
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-22 : 10:27:14
Ahaa, I only tested Scalar Functions. You're correct indeed.

Not sure what the SMO object is, but have a look at sys.sql_expression_dependencies if you're using SQL 2008, sys.sql_dependencies (deprecated) if you're using SQL 2005.
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-22 : 10:29:11
Saw the Dependency Walker Class?
Go to Top of Page

baro1
Starting Member

6 Posts

Posted - 2011-07-22 : 10:35:45
quote:
Originally posted by russell

Saw the Dependency Walker Class?



nope, I just see it now and thats the EXACT thing I was in search for. Thanks mate
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-22 : 11:24:57
Glad it helped.
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-07-22 : 11:49:43
Very interesting - learned a few new things!! Thanks russell.

Not clear to me what determines whether you need to have the dependent objects defined before you can create a function. Whether that is true for all table-valued functions, or whether it is some other characteristic that causes that requirement.
Go to Top of Page

russell
Pyro-ma-ni-yak

5072 Posts

Posted - 2011-07-22 : 11:58:10
I'm not sure. I learned a few things from this too

I might have to do a little testing on it.

Also, I'm no expert with SMO programming, but have been playing around with it a bit lately.

This is one of the best things about forums like this -- we can all learn something from each other!
Go to Top of Page
   

- Advertisement -