473,569 Members | 2,929 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Multiple recordsets continued

I was inspired by the recent discussion of returning multiple recordsets to
ADO from a stored procedure. (Amazed is probably more accurate). I asked
about how to accomplish same with Oracle and got a nudge in the right
direction from Mr. Kreft. I promised to provide details once working, so
here it is.

The code is shown below. My next step is to build this technique into my
application. I'm hoping for substantial performance gain.

This is totally new to me, I'd welcome any constructive criticism. By the
same token, I got it working, so I'll be happy to attempt to answer any
questions anyone might have.

Randy Harris
In Oracle I created this package and stored procedure:

/* A PL/SQL book said that the cursor object
must be declard in a package */
CREATE OR REPLACE PACKAGE OraOLEDB AS
TYPE m_refcur IS REF CURSOR;
END OraOLEDB;
/

/* =============== =============== ===== */
/* This procedure will return two REF cursors */
/* I added a couple of IN parameters to prove I could */
CREATE OR REPLACE PROCEDURE getrecs(
firstweek IN NUMBER,
lastweek IN NUMBER,
firstrs OUT OraOLEDB.m_refc ur,
secondrs OUT OraOLEDB.m_refc ur)
IS

BEGIN
/* Define the first cursor that will become a recordset */
OPEN firstrs FOR
SELECT weekid, weekstart
FROM weeks_tbl
WHERE weekid BETWEEN firstweek AND lastweek ;

/* And now a second */
OPEN secondrs FOR
SELECT tablename, updateseq
FROM concurrence ;

END getrecs;
/
Here's the VBA procedure that calls the SP:

Private Sub MultiRecs()

Dim conn As New ADODB.Connectio n
Dim rst1 As New ADODB.Recordset
Dim rst2 As New ADODB.Recordset

Dim cmd As New ADODB.Command

With conn
.Provider = "OraOLEDB.Oracl e"
.Open "data source=" & OracleDB & ";", dbUser, dbPass
End With

cmd.ActiveConne ction = conn
cmd.Properties( "PLSQLRSet" ) = True
cmd.CommandType = adCmdText
cmd.CommandText = "{Call getrecs (420, 430) }"

' this calls the procedure and retrieves the cursors
' the first recordset is created
Set rst1 = cmd.Execute

While Not rst1.EOF
Debug.Print rst1(0), rst1(1)
rst1.MoveNext
Wend

' Now call the NextRecordset Method
Set rst2 = rst1.NextRecord set

While Not rst2.EOF
Debug.Print rst2(0), rst2(1)
rst2.MoveNext
Wend

rst1.Close
rst2.Close
End Sub

Dec 10 '05 #1
16 5710
Randy Harris wrote:
The code is shown below. My next step is to build this technique into my
application. I'm hoping for substantial performance gain.


Why would getting one recordset composed of two recordsets result in a
substantial performance gain as compared with just getting two
recordsets?

1. It's true that you will send one command instead of two, but will
you not get back the same data in the same form (form the noun not form
the Access Object) and is the transport of this data not likely to be
the chief time-consuming activity of the whole procedure;

2. In MS-SQL we can create and use the cursor in the stored procedure
and get only the second recordset (assuming the first is used only as
fodder for the second); can this be done in Oracle;

3. How often will we write Procedures that will return multiple
recordsets, which might be rewritten as Joins to return the required
data;

4. How efficient is it to hold two recordsets in memory if we are using
them consecutively, that is, if we use the first, then use the second
and never return to the first;

4. In cases where field structure is the same will Unions or multiple
recordsets be more efficient?

These are idle thoughts of my own that I am pondering; I'm currently at
this stage:

1. I don't have anything running so slowly or inefficiently that I'm
going to rewrite it using multiple recordsets;
2. I'll keep multiples in mind when I program ADO recordsets in the
future;
3. I already use Unions when I have two recordsets with identical
fields that I want to use, using an absolute field defined something
like "A" as WhichGroup for the first and "B" as WhichGroup for the
second; this troubles me and maybe I'll replace it with multiples
recordsets;
4. With SQL 2000 and 2005 VBA is almost redundant; there is little I
can do in a VBA module that I can't do in a SPROC; but do I really
wanna have the server do all the work sharing it's CPU time with a
bunch of clients, rather than having the client machine do all the
work, sharing its CPU time with nothing?

As an aside T-SQL can even act as an adjunct to VBA. Don't want the
hassle of API functions to get Zulu time? Have access to an MS-SQL
sever? Use its functions then:
CurrentProject. Connection.Exec ute("SELECT GETUTCDATE()"). Collect(0)
2005-12-10 03:24:26

If one extends this to UDFs then one could do everything in the server
and UDFs would be the repository for ones code.
And of course, this doesn't have to have anything at all to do with
your data or your type of database Your data could be an mdb or oracle
or whatever and you could access functions from some central business
rules/ function ms-sql code repository on the other side of the earth,
or on your local hard drive. That is we could all share the same
functions and have access to instant updates and additions.

I'm digressing, sorry.

Lyle

Dec 10 '05 #2

"Lyle Fairfield" <ly***********@ aim.com> wrote in message
news:11******** **************@ g43g2000cwa.goo glegroups.com.. .
Randy Harris wrote:
The code is shown below. My next step is to build this technique into my
application. I'm hoping for substantial performance gain.


Why would getting one recordset composed of two recordsets result in a
substantial performance gain as compared with just getting two
recordsets?

1. It's true that you will send one command instead of two, but will
you not get back the same data in the same form (form the noun not form
the Access Object) and is the transport of this data not likely to be
the chief time-consuming activity of the whole procedure;

2. In MS-SQL we can create and use the cursor in the stored procedure
and get only the second recordset (assuming the first is used only as
fodder for the second); can this be done in Oracle;

3. How often will we write Procedures that will return multiple
recordsets, which might be rewritten as Joins to return the required
data;

4. How efficient is it to hold two recordsets in memory if we are using
them consecutively, that is, if we use the first, then use the second
and never return to the first;

4. In cases where field structure is the same will Unions or multiple
recordsets be more efficient?

These are idle thoughts of my own that I am pondering; I'm currently at
this stage:

1. I don't have anything running so slowly or inefficiently that I'm
going to rewrite it using multiple recordsets;
2. I'll keep multiples in mind when I program ADO recordsets in the
future;
3. I already use Unions when I have two recordsets with identical
fields that I want to use, using an absolute field defined something
like "A" as WhichGroup for the first and "B" as WhichGroup for the
second; this troubles me and maybe I'll replace it with multiples
recordsets;
4. With SQL 2000 and 2005 VBA is almost redundant; there is little I
can do in a VBA module that I can't do in a SPROC; but do I really
wanna have the server do all the work sharing it's CPU time with a
bunch of clients, rather than having the client machine do all the
work, sharing its CPU time with nothing?

As an aside T-SQL can even act as an adjunct to VBA. Don't want the
hassle of API functions to get Zulu time? Have access to an MS-SQL
sever? Use its functions then:
CurrentProject. Connection.Exec ute("SELECT GETUTCDATE()"). Collect(0)
2005-12-10 03:24:26

If one extends this to UDFs then one could do everything in the server
and UDFs would be the repository for ones code.
And of course, this doesn't have to have anything at all to do with
your data or your type of database Your data could be an mdb or oracle
or whatever and you could access functions from some central business
rules/ function ms-sql code repository on the other side of the earth,
or on your local hard drive. That is we could all share the same
functions and have access to instant updates and additions.

I'm digressing, sorry.

Lyle


Good questions, and food for thought. Perhaps my judgment might be clouded
by my enthusiasm for the novelty of this approach.

Regarding question #1: The particular areas where I'm hoping this might be
beneficial involve consecutively passing multiple SQL statements to Oracle
then retrieving or updating recordset data, then closing. In several places
there are 4 to 6 operations. My thinking is that there is "handshake" time
involved in each of these operations. Perhaps the "stack up" of that time
can be reduced by use of the single SP. The quantity of data passed should
be unchanged from the technique used currently.

#3: I think there are some places where properly defined joins could reduce
the number of retrieval recordsets.

#5: The tables involved have dissimilar structure, but unions would be more
efficient if usable.

Perhaps wishful thinking. I don't know. I can think of only one way to find
out for certain.

Randy

Dec 10 '05 #3
Lyle,
Some answers.

1) But there is more to it than ths, when you send a command to a server
database (SQL anyway) there is time spent compiling that command and doing
things like resolving execution plans. Sending one command to retrieve
multiple recordsets will impact on these and should show a performance
increase in certain cases.

Of course (as with anything db) this is not an absolute and would need to be
tested for a particular situation to see if a performance increase occurs.

2) outside my area of expertise so I'll leave this to Randy.

3) I would use this technique for situations where I wanted either disparate
recordsets or ones where I need to navigate through the recordsets
independently. In situations where previously I would have used joins I
tend to use shaped recordsets as these can show a performance improvement
over standard joined recordsets.

4) This is one of theose situation where you would have to try it and see.

BTW, I know that Randy's example shows him consuming the recordsets in
sequence you don't have to do this though. You can do this

Function xxxx()
Dim loCon As ADODB.Connectio n
Dim rs1 As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim rs3 As ADODB.Recordset

Set rs1 = New ADODB.Recordset

Const CONN_STRING = "File Name=c:\a.udl"

Set loCon = New ADODB.Connectio n
With loCon
.CursorLocation = adUseClient
.ConnectionStri ng = CONN_STRING
.Open
Set rs1 = .Execute("SELEC T * FROM scheme.plsuppm SELECT * FROM
scheme.slcustm" )
End With

' NOTE .clone
Set rs2 = rs1.Clone
' Now .NextRecordset
Set rs3 = rs1.NextRecords et

' At this point
' rs2 contains the first recordset
' rs3 contains the second recordset
End Function

--
Terry Kreft

"Lyle Fairfield" <ly***********@ aim.com> wrote in message
news:11******** **************@ g43g2000cwa.goo glegroups.com.. .
Randy Harris wrote:
The code is shown below. My next step is to build this technique into my
application. I'm hoping for substantial performance gain.


Why would getting one recordset composed of two recordsets result in a
substantial performance gain as compared with just getting two
recordsets?

1. It's true that you will send one command instead of two, but will
you not get back the same data in the same form (form the noun not form
the Access Object) and is the transport of this data not likely to be
the chief time-consuming activity of the whole procedure;

2. In MS-SQL we can create and use the cursor in the stored procedure
and get only the second recordset (assuming the first is used only as
fodder for the second); can this be done in Oracle;

3. How often will we write Procedures that will return multiple
recordsets, which might be rewritten as Joins to return the required
data;

4. How efficient is it to hold two recordsets in memory if we are using
them consecutively, that is, if we use the first, then use the second
and never return to the first;

4. In cases where field structure is the same will Unions or multiple
recordsets be more efficient?

These are idle thoughts of my own that I am pondering; I'm currently at
this stage:

1. I don't have anything running so slowly or inefficiently that I'm
going to rewrite it using multiple recordsets;
2. I'll keep multiples in mind when I program ADO recordsets in the
future;
3. I already use Unions when I have two recordsets with identical
fields that I want to use, using an absolute field defined something
like "A" as WhichGroup for the first and "B" as WhichGroup for the
second; this troubles me and maybe I'll replace it with multiples
recordsets;
4. With SQL 2000 and 2005 VBA is almost redundant; there is little I
can do in a VBA module that I can't do in a SPROC; but do I really
wanna have the server do all the work sharing it's CPU time with a
bunch of clients, rather than having the client machine do all the
work, sharing its CPU time with nothing?

As an aside T-SQL can even act as an adjunct to VBA. Don't want the
hassle of API functions to get Zulu time? Have access to an MS-SQL
sever? Use its functions then:
CurrentProject. Connection.Exec ute("SELECT GETUTCDATE()"). Collect(0)
2005-12-10 03:24:26

If one extends this to UDFs then one could do everything in the server
and UDFs would be the repository for ones code.
And of course, this doesn't have to have anything at all to do with
your data or your type of database Your data could be an mdb or oracle
or whatever and you could access functions from some central business
rules/ function ms-sql code repository on the other side of the earth,
or on your local hard drive. That is we could all share the same
functions and have access to instant updates and additions.

I'm digressing, sorry.

Lyle

Dec 10 '05 #4
I had to test. If you see something I didn't optimize correctly,
please, let me know.
The current connection is to an internet enabled MS-SQL server in
California (I am near Toronto about 4000 km away). I am using a cable
modem (Your download speed : 3133 kbps or 391.6 KB/sec.Your upload
speed : 597 kbps or 74.6 KB/sec.).
FFDBATransactio ns has 296 rows; 4060148Transact ions has 867 rows.
I interpret the results to show that multiple recordset retrieval has
about a 0.01 second advantage over the retrieval of two separate
recordsets under these conditions.

- code is left aligned to try to prevent news client mangling.

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const Iterations As Long = 10
Private Const SQL1 As String = "SELECT * FROM FFDBATransactio ns"
Private Const SQL2 As String = "SELECT * FROM [4060148Transact ions]"

Private Sub TwoRecordSets()
Dim r(2) As ADODB.Recordset
Dim t As Long
Dim z As Long
t = GetTickCount()
For z = 1 To Iterations
Set r(0) = CurrentProject. AccessConnectio n.Execute(SQL1)
With r(0)
While .State <> adStateOpen
Wend
..Close
End With
Set r(1) = CurrentProject. AccessConnectio n.Execute(SQL2)
With r(1)
While .State <> adStateOpen
Wend
..Close
End With
Next z
Debug.Print GetTickCount - t '8201,8162,8131 ,8171
End Sub

Private Sub OneMultipleReco rdSetofTwoRecor dsets()
Dim r(2) As ADODB.Recordset
Dim s As String
Dim t As Long
Dim z As Long
s = "SET NOCOUNT ON;" & SQL1 & ";" & SQL2 & ";SET NOCOUNT OFF"
t = GetTickCount()
For z = 1 To Iterations
Set r(0) = CurrentProject. Connection.Exec ute(s)
With r(0)
While .State <> adStateOpen
Wend
Set r(1) = .NextRecordset
..Close
r(1).Close
End With
Next z
Debug.Print GetTickCount - t '8101,8071,8042 ,8062
End Sub

Dec 10 '05 #5
You've deflated my enthusiasm for this... somewhat.

I think there might still be the possibility of some advantage, despite the
negligible difference you've demonstrated. As Terry pointed out, a
significant portion of the time involved would be the compile and plan time
at the server. Perhaps the server has cached these as you submit the same
SQL repeatedly? If you were to set Iterations to 1 and run the same test,
might the results reflect less time actually passing data across the network
and a higher percentage of "overhead" time?

The other reason that I still hold out some hope that this technique might
have promise is this. When dynamic SQL is passed to the server it must
always be parsed and compiled at run time. By using a stored procedure, I'm
hoping that the SQL will be kept precompiled.

Randy
"Lyle Fairfield" <ly***********@ aim.com> wrote in message
news:11******** **************@ g49g2000cwa.goo glegroups.com.. .
I had to test. If you see something I didn't optimize correctly,
please, let me know.
The current connection is to an internet enabled MS-SQL server in
California (I am near Toronto about 4000 km away). I am using a cable
modem (Your download speed : 3133 kbps or 391.6 KB/sec.Your upload
speed : 597 kbps or 74.6 KB/sec.).
FFDBATransactio ns has 296 rows; 4060148Transact ions has 867 rows.
I interpret the results to show that multiple recordset retrieval has
about a 0.01 second advantage over the retrieval of two separate
recordsets under these conditions.

- code is left aligned to try to prevent news client mangling.

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const Iterations As Long = 10
Private Const SQL1 As String = "SELECT * FROM FFDBATransactio ns"
Private Const SQL2 As String = "SELECT * FROM [4060148Transact ions]"

Private Sub TwoRecordSets()
Dim r(2) As ADODB.Recordset
Dim t As Long
Dim z As Long
t = GetTickCount()
For z = 1 To Iterations
Set r(0) = CurrentProject. AccessConnectio n.Execute(SQL1)
With r(0)
While .State <> adStateOpen
Wend
.Close
End With
Set r(1) = CurrentProject. AccessConnectio n.Execute(SQL2)
With r(1)
While .State <> adStateOpen
Wend
.Close
End With
Next z
Debug.Print GetTickCount - t '8201,8162,8131 ,8171
End Sub

Private Sub OneMultipleReco rdSetofTwoRecor dsets()
Dim r(2) As ADODB.Recordset
Dim s As String
Dim t As Long
Dim z As Long
s = "SET NOCOUNT ON;" & SQL1 & ";" & SQL2 & ";SET NOCOUNT OFF"
t = GetTickCount()
For z = 1 To Iterations
Set r(0) = CurrentProject. Connection.Exec ute(s)
With r(0)
While .State <> adStateOpen
Wend
Set r(1) = .NextRecordset
.Close
r(1).Close
End With
Next z
Debug.Print GetTickCount - t '8101,8071,8042 ,8062
End Sub


Dec 10 '05 #6
Running them 6 times each but not repeatedly I get:

TwoRecordSets
0901 0831 1001 0901 0821 0821

OneMultipleReco rdSetofTwoRecor dsets
0801 0821 0802 0801 0801 0812

Dec 10 '05 #7
BTW, older people like me may not get over being astonished at getting
2 recordsets and more than 1000 records from another computer situated
more than 4000 km away in less than one second using a $1000 computer
and a $130 program and a $48 monthly (all amounts CAD) internet
connection.
If a teacher had demonstrated this in my high school days (the early
fifties) he/she would probably have been checked out for witchcraft!

Dec 10 '05 #8
"Randy Harris" <ra***@SpamFree .com> wrote in
news:9O******** ***********@new ssvr29.news.pro digy.net:
The other reason that I still hold out some hope that this
technique might have promise is this. When dynamic SQL is passed
to the server it must always be parsed and compiled at run time.
By using a stored procedure, I'm hoping that the SQL will be kept
precompiled.


That's not true for MS SQL, if I'm not mistaken. If it's sent the
same SQL a second time, it uses a cached query plan for it. I don't
know how much flexibility there is there, e.g., if all that's
changed is the *value* searched for in a WHERE clause, but the
query
is otherwise identical, the query plan might be cached. You'd have
to look at the documentation for your particular db engine, though.

It seems to me that this technique would be most useful to reduce
load on a server and to control timeing. If, for instance, you have
a process that needs to retrieve both recordsets before it can make
the UI available to the user, it might make more sense to retrieve
those two recordsets in a single request, since the user can't
doing
anything with the first one by itself. If you send two requests,
another request could end up tying up the server before it has a
chance to get to the second request, leading to lag time in your
application as it waits for the second result set.

With multiple recordsets returned, if the server queues the queries
them together (as opposed to treating them as independent and
perhaps interleaving someone else's requests between them), then
you
potentially improve the performance of your application.

You're also consuming fewer resources on the server, so you're
allowing others to work better.

But I'd think these issues would be significant only in an app that
runs against a server that is under very heavy load. On the other
hand, if there's potential for an app to grow in that direction,
you
might want to implement this approach at the beginning to insure
maximum scalability.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Dec 10 '05 #9

"Lyle Fairfield" <ly***********@ aim.com> wrote in message
news:11******** **************@ f14g2000cwb.goo glegroups.com.. .
BTW, older people like me may not get over being astonished at getting
2 recordsets and more than 1000 records from another computer situated
more than 4000 km away in less than one second using a $1000 computer
and a $130 program and a $48 monthly (all amounts CAD) internet
connection.
If a teacher had demonstrated this in my high school days (the early
fifties) he/she would probably have been checked out for witchcraft!


LOL! Technology is a wonder. Imagine what it will likely be 50 years from
now. No reason to think there will be less change in the next 50 years than
there were in the last 50. You and I are unlikely to witness it, but it's
still something to ponder.

Dec 10 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
16495
by: (Pete Cresswell) | last post by:
I posted this in the MS Access group, but no luck. ------------------------------------------ I've got another stored procedure in the same app that returns multiple recordsets and the code works. But now I've written another SP and the code traps out with the 3251 message. The SP is writing two recordsets. When I run the SP in Query...
3
2691
by: sans_spam | last post by:
I want to pull 2 different recordsets using 2 different stored procedures using the same Data Connection. Below is the code that I currently have, but I'm getting an 'Object Required' error message. Am I doing this correctly, or at least headed in the right direction? Can someone tell me the most efficient way (provide a code example) to pull...
2
2240
by: Keith Chadwick | last post by:
I prefer to use stored procedures over having sql statements sitting in my ..NET code. My problem is I can not figure out how get .NET to understand there are multiple recordsets coming back. Each of the recordsets is returning xml data and if called individually would be called as : Dim myCmd as SqlCommand=New...
8
6691
by: Tull Clancey | last post by:
Hi, hope someone can help. I'm writing a decent size app as a first project in Net, have been writing in VB for years. I've stumbled on a small problem, I can't open two connections to a database at the same time, even if the connections are in different classes. Am I doing something compeltely idiotic or is this not as easy at it used...
12
17630
by: Scott | last post by:
Front-end Access 2000 I have a stored procedure that has 2 parameters BusinessUnitID and Year. It returns multiple record sets (5 to be exact). I thought I could use a Pass through query but that only returns the first record set. I thought I could use ADO but that does not seem to work. I get an Error
6
6815
by: blue875 | last post by:
Hello helper people who are smarter than me: I have a form that needs to submit multiple queries to different tables during one Sub's execution. Some sections are as simple as: 1| With rst 2| .Open query1 3| .Close 4| .Open query2 5| End With
0
2353
by: nachiket2k2 | last post by:
Hi, I am using VB 6.0, ADO 2.0 with MS Access 2000 Database. in a vb form, i need to fatch data from 3 different tables (ABC.MDB). it will be a tedious job if i create 3 connections with 3 recordsets. is it possible to do programming in such a way that we can use multiple recordsets with SAME connection? firing SQL statments one after the...
3
10022
by: Dooza | last post by:
Hi there, I have a Stored Procedure in SQL 2000 that takes 10 input paremeters, and outputs 11 recordsets, not rows, but 11 different SELECT statements. The purpose of this is to for a menu system in a store. If all the inputs are NULL, then just the top level categories are output in the first recordset. The ID of each category will then...
0
2828
it0ny
by: it0ny | last post by:
Hi guys, thanks I am fairly new to this forum so I hope I chose the right place to post this question. I try to make my program printout a deposit's report. I created a class to store the printing printing data and the actual database data in a recordset. the class looks like this: Public Class BRPDD 'Balance Report PrintingDocument Data ...
0
7707
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
1
7688
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6306
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5238
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3670
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3663
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2123
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1232
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
964
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.