Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 52 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
52
Dung lượng
1,6 MB
Nội dung
existing location or the ID of a newly added location if the location name doesn’t already exist. Because this property might not get set, either deliberately or because of errors, you must be able to give it a null value, so the Guid value type is not suitable here. Guid? is also not appropriate because it won’t be recognized in SQL Server. Instead, you use the SqlGuid class from the System.Data.SqlTypes namespace: public class Sprocs { [SqlProcedure] public static int AddStoryLocation(Guid storyId, string location, out SqlGuid locationId) { The code starts by setting the output parameter to a null value (SqlGuid.Null) in case of error: locationId = SqlGuid.Null; The remaining code is placed in a try catch structure to accommodate errors. First, a context con- nection is created, along with an associated using block: try { using (SqlConnection conn = new SqlConnection(“context connection=true”)) { The context connection and story ID are then used to check if the specified story ID refers to an existing row in the Story table. The code attempts to obtain the name of the story as a simple test, and executes the generated command using the ExecuteScalar() method to retrieve the name: SqlCommand getStoryCmd = new SqlCommand( “SELECT Name FROM Story WHERE StoryId = @StoryId”, conn); getStoryCmd.Parameters.Add(new SqlParameter(“@StoryId”, SqlDbType.UniqueIdentifier)).Value = storyId; conn.Open(); string storyName = getStoryCmd.ExecuteScalar() as string; conn.Close(); The connection remains open only for the minimum time — just while the command executes. That’s common to all the code in this method, and ensures that the context connection is used as efficiently as possible. If there is no story, a name won’t be returned. If that happens, it’s reported using the SqlContext.Pipe.Send() method that you saw earlier in the chapter, and the method terminates with the appropriate status report, ReturnValue.NoStory: if (storyName == null) { SqlContext.Pipe.Send(“No story with an ID of “ + storyId.ToString() + “ exists. Unable to add location.”); return (int)ReturnValue.NoStory; } 451 SQL Server CLR Integration 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 451 If the story exists, the next step is to check whether the specified location exists in the Location table. That uses similar code, but retrieves a GUID ID rather than a string value. Again, the query may return null, and because you can’t use a Guid variable to store a null value, you use the generic nullable type Guid? to store the query result: SqlCommand getLocationCmd = new SqlCommand( “SELECT LocationId FROM Location WHERE Location = @Location”, conn); getLocationCmd.Parameters.Add(new SqlParameter(“@Location”, SqlDbType.VarChar, 100)).Value = location; conn.Open(); Guid? existingLocationId = getLocationCmd.ExecuteScalar() as Guid?; conn.Close(); Generic nullable types have a HasValue property to check for null values. You use it to see if there is an existing location, and if there is, you set the output locationId parameter using the Guid?.Value property: if (existingLocationId.HasValue) { locationId = existingLocationId.Value; If both the story and location exist, it’s possible that there is already a row in the StoryLocation table that links these records. To avoid duplication, the next step checks for such a row by filtering the data by the IDs of the story and location. Again, a Guid? variable is used to obtain the result: SqlCommand getStoryLocationCmd = new SqlCommand( “SELECT StoryLocationId FROM StoryLocation “ + “WHERE StoryId = @StoryId AND LocationId = @LocationId”, conn); getStoryLocationCmd.Parameters.Add(new SqlParameter(“@StoryId”, SqlDbType.UniqueIdentifier)).Value = storyId; getStoryLocationCmd.Parameters.Add(new SqlParameter( “@LocationId”, SqlDbType.UniqueIdentifier)).Value = locationId.Value; conn.Open(); Guid? existingStoryLocationId = getStoryLocationCmd.ExecuteScalar() as Guid?; conn.Close(); If the StoryLocation table already contains an entry, there’s nothing more to do. That being the case, the code reports the result and exits, returning the ReturnValue.LocationExists status code: if (existingStoryLocationId.HasValue) { SqlContext.Pipe.Send(“Story already has the “ + location + “ location.”); return (int)ReturnValue.LocationExists; } } 452 Chapter 11 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 452 Alternatively, it’s possible that the story exists but the location doesn’t. In that case, you add a new row to the Location table and then retrieve the ID of the new row. The second part, retrieving the row ID, can use the command you created earlier because the location names will match: else { SqlCommand insertLocationCmd = new SqlCommand( “INSERT INTO Location (Location) VALUES (@Location)“, conn); insertLocationCmd.Parameters.Add(new SqlParameter(“@Location”, SqlDbType.VarChar, 100)).Value = location; conn.Open(); insertLocationCmd.ExecuteNonQuery(); existingLocationId = getLocationCmd.ExecuteScalar() as Guid?; conn.Close(); Now that you know the location ID, you can set the output parameter: locationId = existingLocationId.Value; The code then sends the client a message to say that a new location has been added. That isn’t essential, but provides useful feedback. A client receiving the message might want to update cached data from the Location table. For example: SqlContext.Pipe.Send(“The “ + location + “ location did not exist, it has been added.”); } Regardless of whether the location already exists, or whether the location was added, the final database operation is to add a row to the StoryLocation table to link the Story and Location table rows. That uses familiar code: SqlCommand insertStoryLocationCmd = new SqlCommand( “INSERT INTO StoryLocation (StoryId, LocationId) “ + “VALUES (@StoryId, @LocationId)“, conn); insertStoryLocationCmd.Parameters.Add(new SqlParameter(“@StoryId”, SqlDbType.UniqueIdentifier)).Value = storyId; insertStoryLocationCmd.Parameters.Add(new SqlParameter( “@LocationId”, SqlDbType.UniqueIdentifier)).Value = locationId.Value; conn.Open(); insertStoryLocationCmd.ExecuteNonQuery(); conn.Close(); A message is also sent to confirm the addition of the story location: SqlContext.Pipe.Send(“Story location added.”); } } 453 SQL Server CLR Integration 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 453 If an exception occurs at any point in the code, the method includes simple exception-handling code to report the problem and terminate with a status code of ReturnValue.UnknownError. You could, of course, include much more error-checking code here to analyze the exception and report in a more spe- cific way — or perhaps even deal with the error and try accessing the database again. That code isn’t included here, purely for brevity: catch (Exception ex) { // Return error and status. SqlContext.Pipe.Send(“An exception occurred. Message: “ + ex.Message); return (int)ReturnValue.UnknownError; } Finally, knowing that everything has gone as planned and that no errors occurred, you can terminate the method by returning the status code ReturnValue.OK (which has the integer value 0): return (int)ReturnValue.OK; } } Okay, so that was quite a lot of code to get through, but again, this method provides a lot of functional- ity. You could write the same stored procedure in SQL — there is nothing .NET-specific here. However, the SQL version of the stored procedure would surely be harder to construct because it’s much easier to write .NET code. .NET code is also relatively easy to debug because you can test it in a client application first and place it in an assembly for CLR integration only when you are 100 percent sure that it does what you want it to. Debugging SQL code is notoriously difficult by comparison. Anyway, having created the assembly, you loaded it into SQL Server and define a stored procedure. You’ve seen how to define SQL stored procedures in some depth already in this book; the only new thing here is the use of the AS EXTERNAL NAME clause to link the stored procedure to your code: CREATE PROCEDURE dbo.AddStoryLocation ( @storyId uniqueidentifier, @location nvarchar(100), @locationId uniqueidentifier OUTPUT ) AS EXTERNAL NAME Ex1104.Sprocs.AddStoryLocation Calling the stored procedure from SQL code also uses familiar syntax. For ease of use, variables are first declared for the parameters and return value: DECLARE @storyId uniqueidentifier DECLARE @location nvarchar(100) DECLARE @locationId uniqueidentifier DECLARE @result int Next, the two input parameters are assigned values: SET @storyId = ‘da47837d-c6a5-490b-96cf-808137d0e760’ SET @location = ‘Jungle’ And then the stored procedure is executed: 454 Chapter 11 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 454 EXEC @result = dbo.AddStoryLocation @storyId, @location, @locationId OUTPUT To report the results, a SELECT query is used to display both the status code and output parameter: SELECT @result AS StatusCode, @locationId AS LocationId To view the messages returned, you had to use the alternate result view by clicking the Messages tab. I hope you’ll agree that this is a nice programming model, and probably one that you’ll use frequently. You may even decide that this way of creating stored procedures is preferable to writing them in SQL code in all situations, and that wouldn’t be a bad decision. There are so many advantages, from addi- tional capabilities, through simpler syntax, to easier debugging, that it’s difficult not to get a little bit excited about this technique. The simpler coding is offset slightly by the additional steps required to deploy CLR integration assemblies, but then those steps are hardly difficult. It takes only a few SQL commands to get up and running, and the results are fantastic. Summary This chapter looked at CLR integration, which is a way to write .NET code that runs inside SQL Server. You learned the basics, and moved on to experiment with .NET code to implement functions and stored procedures. To summarize, you learned how: ❑ .NET features can extend the functionality available in SQL Server, and how writing various database object in C# can simplify your development. ❑ CLR integration works, including how to enable CLR integration in SQL Server, and how to load and remove .NET assemblies to and from a database. You also looked at the requirements of CLR code, including what .NET assemblies are available to you by default, and what C# pro- gramming elements to avoid (such as destructors). ❑ To register .NET types and methods for use in SQL Server. ❑ To use context connections to access the local database, and how to use the SqlPipe class to send data to the client. You also explored common features available to you from CLR inte- grated code. ❑ To create scalar, table-valued, and aggregate functions. You looked at the code structures required to implement the various function types and the attributes to control them, and you learned how to register each function type and use it within SQL Server. ❑ To create stored procedures. You saw how to combine the power and flexibility of .NET code with SQL stored procedures. This illustrated how complicated operations involving extensive data access and logic are much easier to create with C# than with SQL. This is the last chapter in this book, and now you are equipped with all the tools you need to create pow- erful database applications using C# and SQL Server. Although you have been using Express products, everything you have learned applies equally to the full versions of Visual Studio and SQL Server. 455 SQL Server CLR Integration 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 455 Many subjects in this book, including CLR integration, have been presented as starting points for you. You’ll find a wealth of information, both online and in other books, that will enable you to expand your knowledge further. Getting a solid foundation in the fundamentals, and having at least basic exposure to more complicated subjects such as CLR integration, will stand you in good stead and make it much eas- ier for you to progress further. I wish you all the best in your quest to write perfect database applications. Thank you for reading! Exercises 1. Which of the following can you create using CLR integrated .NET code? a. Views b. Aggregate functions c. User-defined types d. Table types e. Stored procedures 2. Outline the steps required to get .NET code running inside SQL Server. 3. How would you access data from CLR integrated code? 4. How would you send row data for a single row to client applications using SqlContext? Give the code to send a row consisting of a GUID ID column called MyTableId and an integer col- umn called MyAmount to the client (with any column values you wish). 5. What attribute would you use to define a class for use as an aggregate function? What property of this attribute is mandatory, and how will it affect the code required for an aggregate function? 456 Chapter 11 44063c11.qxd:WroxBeg 9/12/06 10:45 PM Page 456 A Installation This appendix provides detailed, step-by-step instructions for installing all the programs you need to try out the examples in this book: ❑ Microsoft .NET Framework 2.0 ❑ Visual C# 2005 Express Edition ❑ SQL Server 2005 Express Edition ❑ SQL Server Management Studio Express ❑ Visual Web Developer 2005 Express Edition If you’ve never installed a program, this might seem quite daunting but don’t worry — the process is simple, especially because you’ll use default options so you won’t have to do any con- figuration. And there’s more good news — all of these programs are free to use. This appendix contains a separate section for each program. However, you won’t necessarily have to install each program individually. If you install Visual C# 2005 Express Edition, .NET Framework 2.0 is installed automatically, and you can also choose to install SQL Server 2005 Express Edition (as detailed later in the Visual C# section). If you already have Visual C# 2005 Express Edition installed without SQL Server 2005 Express Edition, you can install SQL Server separately There are two very important points to note before you begin: ❑ If you have any previous versions of SQL Server, Visual Studio, or the .NET Framework 2.0 installed on your computer, you must uninstall them first. To avoid problems, the uninstal- lations must be performed in a specific order. See http://msdn.microsoft.com/ vstudio/express/support/uninstall for details. ❑ You must have the current version of the .NET Framework 2.0 installed before you can install SQL Server 2005 Express Edition. To ensure that you have the correct version of the .NET Framework 2.0 installed, follow the subset of instructions you need in the order that they are listed in this appendix. If you already have the .NET Framework installed, you can check which version it is by going to Control Panel and using the Add or Remove Programs feature to examine the details of your installation. 44063ca.qxd:WroxBeg 9/12/06 3:55 PM Page 457 .NET Framework 2.0 For the purposes of this book, the easiest way to install .NET Framework 2.0 is to install Visual C# 2005 Express Edition. However, should you ever need to install the .NET Framework independently, go to http://msdn.microsoft.com/netframework/ and follow the instructions you find there. Visual C# 2005 Express Edition To install Visual C# 2005 Express Edition, follow these steps: 1. Go to http://msdn.microsoft.com/vstudio/express and click the link for Visual C# 2005 Express Edition. You’ll find a product overview and a feature tour as well as a Download Now link. 2. Click Download Now. You’re reminded about uninstallation, and receive information about reg- istration and a download link for the installation file, vcssetup.exe. 3. Download the file and run it, or run it when prompted after you click the download link. You may see a security warning — if you do, click Run. The files extract to a temporary folder and then a dialog box appears, telling you that Setup is installing components. After the components are installed, the setup wizard opens, as shown in Figure A-1. 4. Click Next. Accept the license agreement (see Figure A-2) to continue installation, and click Next again. 5. Choose optional products: Microsoft MSDN 2005 Express Edition and SQL Server 2005 Express Edition. Obviously SQL Server is required for this book, but it’s a good idea to select MSDN 2005 as well. (MSDN is Microsoft’s documentation for all its technologies. In this instance you install only the relevant Visual C# and SQL Server information. You can access this information online, but you’ll have faster access if you install it.) Click Next. Figure A-1: The setup wizard 458 Appendix A 44063ca.qxd:WroxBeg 9/12/06 3:55 PM Page 458 Figure A-2: The license agreement 6. The Destination Folder page (see Figure A-3) asks you to select an install location. Select the folder you want and click Install. (Figure A-3 shows a D:\ drive installation.) 7. The Download and Install Progress page (see Figure A-4) keeps you posted on the process. As you can see, the current version of the .NET Framework is installed automatically. Figure A-3: The Destination Folder page 459 Installation 44063ca.qxd:WroxBeg 9/12/06 3:55 PM Page 459 Figure A-4: The Download and Install Progress page 8. When the setup completes, you’re notified that installation was successful and that you must register the software. The instructions onscreen tell you how to do this. If you decide to register later (you have to register within 30 days), you can use the Register Product option on the Help menu. SQL Server Express To download and install SQL Server 2005 Express Edition, follow these steps: 1. Go to http://msdn.microsoft.com/vstudio/express and click the link for SQL Server 2005 Express Edition. 2. Click Download Now. You’re given a reminder about uninstallation, information about registra- tion, and a selection of download options for SQL Server 2005 products. Under the Install SQL Server 2005 Express Edition heading, click the Download link. 3. When the download completes, open sqlexpr.exe. You may see a security warning — if you do, click Run. You have to accept the license agreement before you can proceed. Click Next. 4. The Installing Prerequisites page tells you what components have to be installed prior to SQL Server setup. An example is shown in Figure A-5. Follow the instructions onscreen. You’re informed when the install has been successful. 5. Click Next to run a system configuration check. The results of the system check display, as shown in Figure A-6. 460 Appendix A 44063ca.qxd:WroxBeg 9/12/06 3:55 PM Page 460 [...]... will not be reflected in the web method response Exercise 4 Solution < /databases> Exercise 5 Solution You would detect the DatabaseNotEnabledForNotificationException... BindingNavigator control, 102 103 , 125 BindingSource control, 91–94, 126, 321 body of stored procedure, 263–264 branching ELSE, 272 GOTO, 272 IF, 272 IF ELSE, 273–275 business objects, 323 C Cache.Add( ) method, 409 CacheDuration property, 401, 408 CacheExpirationPolicy property, 408 Cache.Insert( ) method, 409 caching data, web services, 401, 410 414 application cache, 404– 410 application state, 402–404... location for SQL Server databases If you didn’t change the default file path when you were installing SQL Server, the path should be C\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data 2 Open SQL Server Management Studio Express Connect to your database server when prompted Right-click Databases in the Object Explorer window and select Attach, as shown in Figure B-1 3 On the Add Databases page, click... Files\Microsoft SQL Server\ MSSQL.1\MSSQL\Data\FolktaleDB.mdf’ , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 102 4KB ) LOG ON ( NAME = N’FolktaleDB_log’, FILENAME = N’C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\FolktaleDB_log.ldf’ , SIZE = 102 4KB , MAXSIZE = 2048GB , FILEGROWTH = 10% ) COLLATE Latin1_General_CI_AS GO 469 44063cb.qxd:WroxBeg 9/12/06 3:55 PM Page 470 Appendix B 4 Click Execute... which parameterless stored procedures are useful indeed, and you can have anywhere between 0 and 2 ,100 parameters for a stored procedure Exercise 4 Solution The following code creates a looping structure that emulates a C# for loop: DECLARE @Counter int DECLARE @MaxValue int SET @Counter = 0 SET @MaxValue = 100 WHILE @Counter < @MaxValue BEGIN Operation code SET @Counter = @Counter + 1 END Exercise 5... Installation progress 464 44063ca.qxd:WroxBeg 9/12/06 3:55 PM Page 465 Installation Visual Web Developer 2005 Express Edition To download and Install Visual Web Developer 2005 Express Edition, follow these steps: 1 Go to http://msdn.microsoft.com/vstudio/express and click the link for Visual Web Developer 2005 Express Edition A product overview displays along with a feature tour and a Download Now link Click... 157 assemblies, adding to SQL Server (CLR), 420–421 atomicity, transactions (databases) , 13 AttachDbFilename property, 72 authentication, 71–72, 114 AutoIncrement property, 124 44063bindex.qxd:WroxBeg 9/12/06 10: 32 PM Page 484 AutoIncrementSeed property AutoIncrementSeed property, 124 AutoIncrementStep property, 124 B backups, databases, 14 BEGIN keyword, 261 BEGIN TRANSACTION keyword, 359 BeginTransaction(... message saying that you can’t change the destination folder This is because Visual Web Developer has a dependency on C# Express so they must be installed in the same location If you don’t have enough space for Visual Web Developer in the same location as C# Express, you’ll have to uninstall C# Express and reinstall it in a location that has enough space for both 4 5 Click Install The Download and Install... 202–205 data reader objects, 210 212 databases closing, 196 connection pooling, 197 creating, 194–196 opening, 196 SqlConnection.Close( ) method, 196 SqlConnection.Open( ) method, 196 state, 196–197 ConnectionState enumeration, 196 ConnectionState.Closed, 196 ConnectionState.Open, 196 ConnectionString property, 194 element, 195 consistency, transactions (databases) , 13 485 Index 44063bindex.qxd:WroxBeg... element, 195 consistency, transactions (databases) , 13 485 Index 44063bindex.qxd:WroxBeg 44063bindex.qxd:WroxBeg 9/12/06 10: 32 PM Page 486 context connection context connection, 423 ContinueUpdateOnError property, 221, 338 controls BindingNavigator, 102 103 BindingSource, 91–94, 321 data-bound, modifying data, 119–125 DataList, 164–165 DetailsView, 166–167 FormView, 166 GridView, 63, 164 . there. Visual C# 2005 Express Edition To install Visual C# 2005 Express Edition, follow these steps: 1. Go to http://msdn.microsoft.com/vstudio/express and click the link for Visual C# 2005 Express. install Visual C# 2005 Express Edition, .NET Framework 2.0 is installed automatically, and you can also choose to install SQL Server 2005 Express Edition (as detailed later in the Visual C# section) Microsoft .NET Framework 2.0 ❑ Visual C# 2005 Express Edition ❑ SQL Server 2005 Express Edition ❑ SQL Server Management Studio Express ❑ Visual Web Developer 2005 Express Edition If you’ve never