Wednesday, December 17, 2008

Unrecognized tag prefix or device filter 'asp'. Intellisense stops working!

In VS.NET 2008, when declaring that all ASP.NET web forms use a MasterPage via the web.config file, intellisense might not work. I've found that if I explicitly declare the MasterPageFile property via the form's Page directive, intellisense begins to work again.

Saturday, August 30, 2008

Simplify & Write Much-Less JavaScript Code with jQuery

jQuery - A New Way to Write Common JavaScript Design Patterns in a Lot Less Code

Click here to visit the jQuery website.

jQuery is a very basic, but very powerful, JavaScript coding methodology and code set for writing common, dynamic, JavaScript-enabled web functionality, using a lot less code than you would use to write the same functionality otherwise. jQuery is, technically, a set of code wrappers: code written by developers that simplify common tasks. They've written what would normally be more complicated coding/design patterns and made them available as easy-to-use methods, classes, etc. What I like the most about jQuery is its 1) ease of use & installation, 2) easy-to-use effects library, and 3) broad-range-browser compatibility.

Installing jQuery

jQuery is simply one JavaScript file (.js)! You simply download the latest version from the jQuery site, then include it in your page, like this:

<script type="text/javascript" src="jquery-1.2.6.js"></script>

Execute Code Not when the Page Loads, but when Every Object on the Page has Loaded, Including All Images

// Add a body.onload event handler, which is called only when // ALL document elements have loaded, including all images: $(document).ready(function() { alert("Hello, this is jQuery-called called!"); });

Showing and Hiding HTML Elements, Gradually

<script type="text/javascript"> <!-- jQuery code, by Mike G. @ DotNetFun.com // Add a body.onload event handler, which is called only when // ALL document elements have loaded, including all images: $(document).ready(function() { // NOTE: ALL FURTHER JAVASCRIPT/JQUERY CODE SHOULD // BE DEFINED WITHIN THIS FUNCTION, EXCEPT FOR OTHER // CLASSES AND FUNCTIONS, OF COURSE. // Faded, gradual showing of a division block; // the callback function is optional. $("#btnSample1").click(function() { // 3,000 milliseconds used here; it can also be // "slow", "normal", or "fast" $("#divSample1").show(3000, divSample1_Callback); }); }); // Callback function for the preceding divSample1 show call: function divSample1_Callback() { alert("This is the result of the callback function - divSample1_Callback.\r\n\r\n" + "Clicking on OK will re-hide the divSample1 block."); // Now, re-hide the divSample1 block, after a 3,000 millisecond // gradual delay/fade: $("#divSample1").hide(3000); } //--> </script> <div id="divSample1" style="display:none">Faded, gradual showing of a division block</div> <button id="btnSample1">Show it</button> Click on the following button to test the show() code.

Toggle the Visibility Between Two Elements/Objects

<script type="text/javascript"> $(document).ready(function() { // Toggles the visibility between two elements/objects: $("#btnSample2").click(function() { $("#spanSample2a,#spanSample2b").toggle(); }); }); </script> <p><b>Click on the following button to test the toggle() code.</b><br /> <span id="spanSample2a">Hello!</span> <span id="spanSample2b" style="display:none">Goodbye!</span> <button id="btnSample2">Toggle it</button></p>

Click on the following button to test the toggle() code.
Hello!

Gradually Show an Element, Sliding Downward

<script type="text/javascript"> $(document).ready(function() { // Faded, gradual showing of a division block, sliding downward: $("#btnSample3").click(function() { $("#divSample3").hide(); $("#divSample3").slideDown("slow"); }); }); </script> <p><b>Click on the following button to test the slideDown() code.</b><br /> <div id="divSample3" style="display:none; background-color:Red; width:100px; height:50px;"></div> <button id="btnSample3">Slide it</button></p>

Click on the following button to test the slideDown() code.

Gradually Show an Element, Sliding Upward

<script type="text/javascript"> $(document).ready(function() { // Faded, gradual showing of a division block, sliding downward: $("#btnSample4").click(function() { $("#divSample4").show(); $("#divSample4").slideUp("slow"); }); }); </script> <p><b>Click on the following button to test the slideDown() code.</b><br /> <div id="divSample4" style="background-color:Red; width:100px; height:50px;"></div> <button id="btnSample4">Slide it</button></p>

Click on the following button to test the slideUp() code.

Toggle the Visibility of an Element/Object, Gradually, Upward & Downward

<script type="text/javascript"> $(document).ready(function() { // Toggles the visibility of an element/object, // in a fading, gradual manner, upward and downward $("#btnSample5").click(function() { $("#divSample5").slideToggle("slow"); }); } </script> <p><b>Click on the following button to test the slideToggle() code.</b><br /> <div id="divSample5" style="display:none; background-color:Red; width:100px; height:50px;"></div> <button id="btnSample5">Slide toggle</button></p>

Click on the following button to test the slideToggle() code.

Friday, June 13, 2008

MS SQL Server 2008 - New Features - SSMS Table Re-creation Prevention

One annoying new feature in SSMS is that when you make a change to a table using the Designer which requires the table to be re-created, such as creating an identity column, by default, you'll get the following message:

Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the option Prevent saving changes that require the table to be re-created.

To prevent this message from re-appearing, perform the following steps:

  1. In SSMS, click on Tools, then Options.
  2. Open up the Designers node.
  3. Click on "Table and Database Designers".
  4. Uncheck the checkbox labeled "Prevent saving changes that require table re-creation".
  5. Click on OK.

Thursday, June 12, 2008

MS SQL Server 2008 - New Features - Auditing

You can now audit specific events in SQL Server 2008

The following steps will walk through how you can setup MS SQL Server 2008 to audit failed logons.

Auditing Failed Logons

  1. Login to MS SQL Server Management Studio (SSMS).
  2. Expand the Security folder.
  3. Right-click on the Audits folder, then click on New Audit....
  4. In the Audit name field, enter "Failed Logins" (without quotes).
  5. Set the Audit Destination to Application Log.
  6. Click on OK.
  7. Under the Audits folder, right-click on Failed Logins, then click on Enable Audit.
  8. Close the success dialog box.
  9. Right-click on the Server Audit Specifications, then click on New Server Audit Specifications....
  10. In the Name field, enter "Failed Logins" (without quotes).
  11. Set the Audit field to Failed Logins.
  12. In the Actions grid, set the Audit Action Type to FAILED_LOGIN_GROUP.
  13. Click on OK.
  14. Under the Server Audit Specifications folder, right-click on Failed Logins, then click on Enable Server Audit Specification.
  15. Test auditing by attempting to logon to the server with invalid logon credentials.
  16. Once that's done, check for an audit event by right-clicking on the Failed Logins Audit, then clicking on View Audit Logs.
  17. The failed logon should appear in the log as well as the Windows' Application Log. Take a look at the statement field--it contains an explanation of the event, something like this: Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 10.1.141.146]

    You should also see this in the Windows' Application log:

Wednesday, June 11, 2008

MS SQL Server 2008 - New Features - SSMS Easier Navigation

Easier SQL Server Management Studio (SSMS) Navigation

One of my biggest complaints with SSMS v9 (2005) is it's more-difficult-to-get-to menu items. For example, in order to open up an Object Explorer for a Registered server, you would have to 1) right-click on the server, 2) navigate to Connect, then 3) click on Object Explorer.

With SSMS v10 (2008), all you need to do is 1) right-click on the server, then 2) click on Object Explorer, leaving out the extra navigational step. Now, you might think this is minutiae, but in the world of fast-paced, busy development and administration, every little second helps. The easier it is to get to what I need to do, the faster I can do it, and the faster I can do it, the more likely I am to meet deadlines, get more done, etc.

Object Explorer All Registered Servers in a Folder

Typically, when I'm working with a set of servers at the same time, such as copying objects from one server to another, setting up replication or mirroring, etc, I open up all of the affected servers in SSMS v9, but I need to do this once for each server. Now, with SSMS v10, I can open up ALL servers within a folder simply by 1) right-clicking on a registered folder and 2) choosing Object Explorer.

All of the servers will appear in the Object Explorer with all of the servers open and ready for managing, saving me time. Again, time is precious, so this is a cool feature in my book!

Select and Edit Top n Rows

Another time-saver is now being able to select the top 1000 rows of a table or view as well as edit the top 200 rows respectively. With prior versions, I'd have to open up Query Analyzer or a new query in SSMS and write a SELECT TOP n query against a table or view. This saves time, especially when you're retrieving rows from very large tables/views.

MS SQL Server 2008 - New Features - SSMS Activity Monitor

New SQL Server Management Studio (SSMS) Activity Monitor

There are many new, awesome features in SQL Server 2008, but one I've been anticipating is something that should've been developed years ago--a graphical, near-real-time charts of performance indicators, such as CPU usage, wait states, I/O usage, etc. In SQL Server 2000, you had to run several system stored procedures, such as sp_who, sp_lock, sp_spaceused, and sp_monitor, to get an understanding of what was going on, and in SQL Server 2005, you have an activity monitor, but it's a grid consisted of rows and columns of data, not anything graphical. Another cool feature in v2008 is a listing of SQL queries deemed "expensive". With this information, you can better ascertain which queries might be impacting SQL Server performance.

Overview Performance Charts

With SQL Server 2008, you get a chart-based view of some of the more important performance indicators. The new Activity Monitor in SQL Server 2008 provides such as view. To get to it, simply right-click on a server in the SSMS Object Explorer pane, then click on Activity Monitor (contrast this with SQL Server 2005, in which you have to drill down into Management folder to get to AM). See the following image for a look Activity Monitor's Overview real-time charts.
SQL Server 2008 Activity Monitor Overview

Recent Expensive Queries and Other Features

This feature provides a near-real-time view of expensive queries, something that can help DBAs and developers get a handle on which queries might be impacting server performance, negatively. Other Activity Monitor features include Processes, Resource Waits, and Data File I/O, all in near-real-time views.

To adjust the refresh wait of all of the information in Activity Monitor (you can't set the refresh rate per individual section), simply right-click on on the Overview/charts area, click on Refresh Interval, then choose a rate.

Filters

You can filter the data in the grid sections by clicking on the filter indicator for the appropriate column and selecting the data/value to filter by, a very cool feature, as you might not want to view all of the information on the grid, only a select view/representation.

Backward Compatibility

SQL Server 2005's Activity Monitor will work with SQL Server 2005 but not with v2000 or earlier releases. One thing I noticed with RC0 is that it doesn't show Processor Time statistics for SQL Server 2005 servers.

Comparing SQL Server 2005's Activity Monitor

In SQL Server 2005, Activity Monitor is limited by Processes, Locks by Object, and Locks by Process, and none of them are graphical. You can't view all of the information on one form. To view each search, you right-click on Activity Monitor, typically in Object Explorer in SSMS, then choose a section. With SQL Server 2008's Activity Monitor, you get to view all of the performance-based information on one form, making it easier to view and manage. SQL Server 2008's new Activity Monitor is a much-welcomed feature!

Monday, June 02, 2008

Properly Reinstalling SQL Server 2005 Reporting Services

  1. Stop the default IIS web site. DO NOT SHUTDOWN IIS.
  2. Delete both SQL Server 2005 Report Server databases.
  3. In Control Panel, click on the Change button for the pertinent SQL Server 2005 install instance.
  4. Continue to select Report Server and the option to remove it.
  5. Reinstall Reporting Services by running the installer on the SQL Server 2005 disc.
  6. Once setup is complete, launch the Reporting Services Configuration tool with the Configuration Tools menu in your Start menu.
  7. Fix any red-X items in the list.
  8. You should be good to go!

Thursday, May 08, 2008

Oracle expdp fails with ORA-31637 and ORA-00832

To resolve this problem, ensure that the shared_pool_size initialization parameter is set to a sufficient value.

Monday, May 05, 2008

Creating a Custom SharePoint (MOSS) 2007 Calendar View Web Part with VS.NET 2005

This conceptual tutorial shows you how to create a custom calendar web part that gets its events from an already-existing calendar in MOSS 2007.

Prerequisites:

Note: This tutorial will be a conceptual one, not one where I go into the actual development of a real application/web part.

  1. Open up VS.NET, then create a new SharePoint-Web Part project.
  2. Make sure a reference to Microsoft.SharePoint.dll is there.
  3. Open up the Web Part .cs (code) file.
  4. Ensure the following using statements are present:
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint.WebPartPages;
  5. Ensure the Web Part class is deriving from the following class:
    System.Web.UI.WebControls.WebParts.WebPart
  6. Something in the Web Part class code file, define variables that might be used, such as the following: private String strListName = "DotNetFun Calendar"; private SPCalendarView calendarView = new SPCalendarView(); private Guid listGuid;
  7. Override the base class' CreateChildControls() method:
    protected override void CreateChildControls()
  8. The CreateChildControls() method should look something like this: protected override void CreateChildControls() { try { SPSecurity.RunWithElevatedPrivileges( delegate() { base.CreateChildControls(); ViewType viewType = ViewType.Month; using (SPWeb web = SPContext.Current.Site.OpenWeb(this.webGuid)) { // Change Cal-view based on if QueryString specifies it: if (Page.Request.QueryString["CalendarPeriod"] != null) { switch (Page.Request.QueryString["CalendarPeriod"].ToString().ToLower()) { case "day": this.calendarView.ViewType = "day"; viewType = ViewType.Day; break; case "week": this.calendarView.ViewType = "week"; viewType = ViewType.Week; break; case "timeline": this.calendarView.ViewType = "timeline"; viewType = ViewType.Timeline; break; default: this.calendarView.ViewType = "month"; viewType = ViewType.Month; break; } } SPList listDotNetFunCalendar = web.Lists[this.strListName]; if (listDotNetFunCalendar.Views["Calendar"] == null) throw new ApplicationException("The Calendar view was not found. Please create one accordingly."); SPView viewDotNetFunCalendar = listDotNetFunCalendar.Views["Calendar"]; if (this.calendarView.ViewGuid != null) viewDotNetFunCalendar = listDotNetFunCalendar.Views[new Guid(this.calendarView.ViewGuid)]; this.listGuid = listDotNetFunCalendar.ID; DateTime dtStart = DateTime.Now; if (this.calendarView.SelectedDate != null) dtStart = DateTime.Parse(this.calendarView.SelectedDate).AddDays(-7); DateTime dtEnd = dtStart.AddMonths(1).AddDays(7); SPQuery query = new SPQuery(); query.Query = String.Format( "<Query>" + "<Where><And>" + "<Geq><FieldRef Name=\"{0}\" />" + "<Value Type=\"DateTime\">{1}</Value></Geq>" + "<Leq><FieldRef Name=\"{0}\" />" + "<Value Type=\"DateTime\">{2}</Value></Leq>" + "</And></Where><OrderBy><FieldRef Name=\"{0}\" /></OrderBy>" + "</Query>", "Start Time", dtStart.ToShortDateString(), dtEnd.ToShortDateString()); viewDotNetFunCalendar.Query = query.Query; web.AllowUnsafeUpdates = true; //viewDotNetFunCalendar.Update(); //System.Web.HttpContext.Current.Response.Write(String.Format("{0}<br />", viewDotNetFunCalendar.Query)); SPCalendarItemCollection items = new SPCalendarItemCollection(); foreach (SPListItem listItem in listDotNetFunCalendar.GetItems(viewDotNetFunCalendar)) { SPCalendarItem calItem = new SPCalendarItem(); calItem.ItemID = listItem["ID"].ToString(); calItem.Title = listItem["Title"].ToString(); calItem.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian); calItem.StartDate = (DateTime)listItem["Start Time"]; calItem.ItemID = listItem.ID.ToString(); calItem.WorkSpaceLink = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); // Only allow color-coding, which requires all all-day // event, if a Month view: if (viewType == ViewType.Month) calItem.IsAllDayEvent = true; calItem.DisplayFormUrl = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); if (listItem["End Time"] != null) { calItem.hasEndDate = true; calItem.EndDate = (DateTime)listItem["End Time"]; } else calItem.hasEndDate = false; if (listItem["Description"] != null) calItem.Description = listItem["Description"].ToString(); if (listItem["Location"] != null) calItem.Location = listItem["Location"].ToString(); // Define CSS based on category: // Note, CSS styles are stored in CORE.CSS, here: // %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033\STYLES // Append "sel" (without quotes) to the CSS Class name to // override the onmouseover CSS changes in the CORE.CSS file. switch (listItem["Category"].ToString()) { case "Programming/Scheduling": calItem.BackgroundColorClassName = "DotNetFunCalendarProgramming"; break; case "Production": calItem.BackgroundColorClassName = "DotNetFunCalendarProduction"; break; case "Ad Sales": calItem.BackgroundColorClassName = "DotNetFunCalendarAdSales"; break; case "Marketing/Promotions": calItem.BackgroundColorClassName = "DotNetFunCalendarMarketing"; break; case "PR": calItem.BackgroundColorClassName = "DotNetFunCalendarPR"; break; case "Online/Interactive": calItem.BackgroundColorClassName = "DotNetFunCalendarInteractive"; break; case "Company Events/HR": calItem.BackgroundColorClassName = "DotNetFunCalendarHR"; break; case "General": calItem.BackgroundColorClassName = "DotNetFunCalendarGeneral"; break; } items.Add(calItem); } // Set calendar-only properties: this.calendarView.DisplayItemFormUrl = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); this.calendarView.EditItemFormUrl = String.Format("/Lists/{0}/EditForm.aspx", this.strListName); this.calendarView.NewItemFormUrl = String.Format("/Lists/{0}/NewForm.aspx", this.strListName); this.calendarView.EnableViewState = true; this.calendarView.DataSource = items; this.calendarView.DataBind(); this.DataBind(); } this.Controls.Add(this.calendarView); }); } catch (Exception err) { this.HandleException(err); } }
  9. Override the base class' RenderContents(HtmlTextWriter writer) method:
    RenderContents(HtmlTextWriter writer)
  10. The RenderContents(HtmlTextWriter writer) method should look something like this: protected override void RenderContents(HtmlTextWriter writer) { SPSecurity.RunWithElevatedPrivileges( delegate() { // Check if current user can add events: bool blnCanAddEvents = false; using (SPWeb web = SPContext.Current.Site.OpenWeb(this.webGuid)) { try { web.Lists[this.strListName].Permissions.CheckPermissions(SPRights.AddListItems); blnCanAddEvents = true; } catch { } } // Render header firstly: StringBuilder sbHeader = new StringBuilder(); sbHeader.AppendLine("<table bgcolor='#05C4D8' align='center' width='100%' border='1' cellpadding='2' cellspacing='2'>"); sbHeader.AppendLine("<tr><th align='center' bgcolor='Black'>"); sbHeader.AppendLine("<font color='#05C4D8' size='4'>DotNetFun PROGRAMMING</font>"); sbHeader.AppendLine("</th></table>"); writer.Write(sbHeader.ToString()); // Render calendar secondly: this.calendarView.RenderControl(writer); // Append color legend: StringBuilder sbLegend = new StringBuilder(); sbLegend.AppendLine("<table align='center' width='100%' border='0'>"); sbLegend.AppendLine("<td width='50%' align='left' valign='top'>"); sbLegend.AppendLine("<b><u>Legend:</u></b><br /><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#72FFF6;padding:2px;'>Programming/Scheduling</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#1AA4C2;padding:2px;'>Production</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#3F8698;padding:2px;'>Ad Sales</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#76D600;padding:2px;'>Marketing/Promotions</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#FF9A00;padding:2px;'>PR</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#E000B6;padding:2px;'>Online/Interactive</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#F51604;padding:2px;'>Company Events/HR</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:White;padding:2px;'>General</label><br />"); sbLegend.AppendLine("</td>"); sbLegend.AppendLine("<td width='50%' align='left' valign='top'>"); sbLegend.AppendLine("<b><u>Options:</u></b><br /><br />"); if (blnCanAddEvents) sbLegend.AppendLine(String.Format("<li><a href=\"/Lists/{0}/NewForm.aspx\">Add New Event</a></li>", this.strListName)); sbLegend.AppendLine(String.Format("<li><a href=\"/Lists/{0}/\">View the Full Calendar</a></li>", this.strListName)); sbLegend.AppendLine(String.Format("<li><a href=\"/_layouts/listfeed.aspx?List={0}\">RSS Feed</a></li>", this.listGuid.ToString())); sbLegend.AppendLine(String.Format("<li><a href=\"http://DotNetFunshare001/_layouts/SubNew.aspx?List={0}\">Alert Me When this Calendar Changes</a></li>", this.listGuid.ToString())); sbLegend.AppendLine("</td></table>"); writer.Write(sbLegend.ToString()); }); }
  11. Ensure that the AssemblyInfo.cs file is using whole, major version numbers and nothing else (e.g., 1.0.0.0).
  12. The code sample in this tutorial makes use of CSS via the MOSS 2007's CORE.CSS master CSS file, located here: %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033\STYLES
  13. Before you can use the Web Part, it must be trusted by declaring it a safe control. Do this by adding something like the following to the site's web.config file, typically, located here, C:\Inetpub\wwwroot\wss\VirtualDirectories\80\web.config:
  14. <SafeControl Assembly="SPDotNetFunCalendarWebpart, Version=52.0.0.0, Culture=neutral, PublicKeyToken=fc6dbd48e3fd5742" Namespace="DotNetFun.SharePoint.WebParts" TypeName="*" />
  15. Add the following line to the AssemblyInfo.cs code file: [assembly: System.Security.AllowPartiallyTrustedCallers()]
  16. Sign the project with a strong-name key, then add it to the GAC, after compiling it, of course.
  17. Go to the settings page of the site on which the calendar list exists and from which data is being retrieved.
  18. Under the Galleries section, click on Web Parts.
  19. Click on the New button.
  20. Check the checkbox for the calendar web part just created.
  21. Click on Populate Gallery.
  22. Add a new Permission Level for this particular type of web part, as shown above, and grant it basic rights plus the Add right, as without Add, it won't work.
  23. The web part is now ready for use on this site.

Sample, entire Web part class code file:

using System; using System.Runtime.InteropServices; using System.Web.UI; using System.Web.UI.WebControls.WebParts; using System.Xml.Serialization; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; using Microsoft.SharePoint.WebPartPages; using System.Text; namespace DotNetFun.SharePoint.WebParts { [Guid("a6b6f461-cc95-4cf3-b419-b0b1b1d20355")] public class SPDotNetFunCalendarWebpart : System.Web.UI.WebControls.WebParts.WebPart { private Guid webGuid = SPContext.Current.Web.ID; private String strListName = "DotNetFun Calendar"; private SPCalendarView calendarView = new SPCalendarView(); private Guid listGuid; public SPDotNetFunCalendarWebpart() { this.ExportMode = WebPartExportMode.All; this.Title = "DotNetFun Programming Calendar"; } protected override void RenderContents(HtmlTextWriter writer) { SPSecurity.RunWithElevatedPrivileges( delegate() { // Check if current user can add events: bool blnCanAddEvents = false; using (SPWeb web = SPContext.Current.Site.OpenWeb(this.webGuid)) { try { web.Lists[this.strListName].Permissions.CheckPermissions(SPRights.AddListItems); blnCanAddEvents = true; } catch { } } // Render header firstly: StringBuilder sbHeader = new StringBuilder(); sbHeader.AppendLine("<table bgcolor='#05C4D8' align='center' width='100%' border='1' cellpadding='2' cellspacing='2'>"); sbHeader.AppendLine("<tr><th align='center' bgcolor='Black'>"); sbHeader.AppendLine("<font color='#05C4D8' size='4'>DotNetFun PROGRAMMING</font>"); sbHeader.AppendLine("</th></table>"); writer.Write(sbHeader.ToString()); // Render calendar secondly: this.calendarView.RenderControl(writer); // Append color legend: StringBuilder sbLegend = new StringBuilder(); sbLegend.AppendLine("<table align='center' width='100%' border='0'>"); sbLegend.AppendLine("<td width='50%' align='left' valign='top'>"); sbLegend.AppendLine("<b><u>Legend:</u></b><br /><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#72FFF6;padding:2px;'>Programming/Scheduling</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#1AA4C2;padding:2px;'>Production</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#3F8698;padding:2px;'>Ad Sales</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#76D600;padding:2px;'>Marketing/Promotions</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#FF9A00;padding:2px;'>PR</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#E000B6;padding:2px;'>Online/Interactive</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:#F51604;padding:2px;'>Company Events/HR</label><br />"); sbLegend.AppendLine("<label style='width:250px;background-color:White;padding:2px;'>General</label><br />"); sbLegend.AppendLine("</td>"); sbLegend.AppendLine("<td width='50%' align='left' valign='top'>"); sbLegend.AppendLine("<b><u>Options:</u></b><br /><br />"); if (blnCanAddEvents) sbLegend.AppendLine(String.Format("<li><a href=\"/Lists/{0}/NewForm.aspx\">Add New Event</a></li>", this.strListName)); sbLegend.AppendLine(String.Format("<li><a href=\"/Lists/{0}/\">View the Full Calendar</a></li>", this.strListName)); sbLegend.AppendLine(String.Format("<li><a href=\"/_layouts/listfeed.aspx?List={0}\">RSS Feed</a></li>", this.listGuid.ToString())); sbLegend.AppendLine(String.Format("<li><a href=\"http://DotNetFunshare001/_layouts/SubNew.aspx?List={0}\">Alert Me When this Calendar Changes</a></li>", this.listGuid.ToString())); sbLegend.AppendLine("</td></table>"); writer.Write(sbLegend.ToString()); }); } private void HandleException(Exception Error) { SPSecurity.RunWithElevatedPrivileges( delegate() { throw Error; //System.Web.HttpContext.Current.Response.Write("<p><b><font color='red'>An error occurred: " + // Error.Message + " " + (Error.StackTrace != null ? Error.StackTrace : "") + // "</font></b></p>"); }); } protected override void OnInit(EventArgs e) { base.OnInit(e); } private enum ViewType { Day, Week, Month, Timeline } protected override void CreateChildControls() { try { SPSecurity.RunWithElevatedPrivileges( delegate() { base.CreateChildControls(); ViewType viewType = ViewType.Month; using (SPWeb web = SPContext.Current.Site.OpenWeb(this.webGuid)) { // Change Cal-view based on if QueryString specifies it: if (Page.Request.QueryString["CalendarPeriod"] != null) { switch (Page.Request.QueryString["CalendarPeriod"].ToString().ToLower()) { case "day": this.calendarView.ViewType = "day"; viewType = ViewType.Day; break; case "week": this.calendarView.ViewType = "week"; viewType = ViewType.Week; break; case "timeline": this.calendarView.ViewType = "timeline"; viewType = ViewType.Timeline; break; default: this.calendarView.ViewType = "month"; viewType = ViewType.Month; break; } } SPList listDotNetFunCalendar = web.Lists[this.strListName]; if (listDotNetFunCalendar.Views["Calendar"] == null) throw new ApplicationException("The Calendar view was not found. Please create one accordingly."); SPView viewDotNetFunCalendar = listDotNetFunCalendar.Views["Calendar"]; if (this.calendarView.ViewGuid != null) viewDotNetFunCalendar = listDotNetFunCalendar.Views[new Guid(this.calendarView.ViewGuid)]; this.listGuid = listDotNetFunCalendar.ID; DateTime dtStart = DateTime.Now; if (this.calendarView.SelectedDate != null) dtStart = DateTime.Parse(this.calendarView.SelectedDate).AddDays(-7); DateTime dtEnd = dtStart.AddMonths(1).AddDays(7); SPQuery query = new SPQuery(); query.Query = String.Format( "<Query>" + "<Where><And>" + "<Geq><FieldRef Name=\"{0}\" />" + "<Value Type=\"DateTime\">{1}</Value></Geq>" + "<Leq><FieldRef Name=\"{0}\" />" + "<Value Type=\"DateTime\">{2}</Value></Leq>" + "</And></Where><OrderBy><FieldRef Name=\"{0}\" /></OrderBy>" + "</Query>", "Start Time", dtStart.ToShortDateString(), dtEnd.ToShortDateString()); viewDotNetFunCalendar.Query = query.Query; web.AllowUnsafeUpdates = true; //viewDotNetFunCalendar.Update(); //System.Web.HttpContext.Current.Response.Write(String.Format("{0}<br />", viewDotNetFunCalendar.Query)); SPCalendarItemCollection items = new SPCalendarItemCollection(); foreach (SPListItem listItem in listDotNetFunCalendar.GetItems(viewDotNetFunCalendar)) { SPCalendarItem calItem = new SPCalendarItem(); calItem.ItemID = listItem["ID"].ToString(); calItem.Title = listItem["Title"].ToString(); calItem.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian); calItem.StartDate = (DateTime)listItem["Start Time"]; calItem.ItemID = listItem.ID.ToString(); calItem.WorkSpaceLink = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); // Only allow color-coding, which requires all all-day // event, if a Month view: if (viewType == ViewType.Month) calItem.IsAllDayEvent = true; calItem.DisplayFormUrl = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); if (listItem["End Time"] != null) { calItem.hasEndDate = true; calItem.EndDate = (DateTime)listItem["End Time"]; } else calItem.hasEndDate = false; if (listItem["Description"] != null) calItem.Description = listItem["Description"].ToString(); if (listItem["Location"] != null) calItem.Location = listItem["Location"].ToString(); // Define CSS based on category: // Note, CSS styles are stored in CORE.CSS, here: // %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033\STYLES // Append "sel" (without quotes) to the CSS Class name to // override the onmouseover CSS changes in the CORE.CSS file. switch (listItem["Category"].ToString()) { case "Programming/Scheduling": calItem.BackgroundColorClassName = "DotNetFunCalendarProgramming"; break; case "Production": calItem.BackgroundColorClassName = "DotNetFunCalendarProduction"; break; case "Ad Sales": calItem.BackgroundColorClassName = "DotNetFunCalendarAdSales"; break; case "Marketing/Promotions": calItem.BackgroundColorClassName = "DotNetFunCalendarMarketing"; break; case "PR": calItem.BackgroundColorClassName = "DotNetFunCalendarPR"; break; case "Online/Interactive": calItem.BackgroundColorClassName = "DotNetFunCalendarInteractive"; break; case "Company Events/HR": calItem.BackgroundColorClassName = "DotNetFunCalendarHR"; break; case "General": calItem.BackgroundColorClassName = "DotNetFunCalendarGeneral"; break; } items.Add(calItem); } // Set calendar-only properties: this.calendarView.DisplayItemFormUrl = String.Format("/Lists/{0}/DispForm.aspx", this.strListName); this.calendarView.EditItemFormUrl = String.Format("/Lists/{0}/EditForm.aspx", this.strListName); this.calendarView.NewItemFormUrl = String.Format("/Lists/{0}/NewForm.aspx", this.strListName); this.calendarView.EnableViewState = true; this.calendarView.DataSource = items; this.calendarView.DataBind(); this.DataBind(); } this.Controls.Add(this.calendarView); }); } catch (Exception err) { this.HandleException(err); } } } }

Wednesday, April 23, 2008

Enabling > 4GB RAM Support with Oracle 10g Running on Windows Server 2003 32-bit Ed.

  1. Add the /3G, USERENV, and /PAE switches to the boot.ini file, on the Windows Server 2003 Server. For example: multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Windows Server 2003" /fastdetect /NoExecute=OptIn /3GB /USERENV /PAE
  2. The account that is used to start the Oracle Service must be given the "Lock Pages in Memory" right. You can do this by a) going to Administrative Tools, from the Start menu or Control Panel, b) opening Local Security Policy, c) opening Local Policies, then d) opening User Rights Assignment; e) open/edit the "Lock Pages in Memory" key, f) then add the Oracle Service account to this list.
  3. Create an AWE_WINDOW_MEMORY String (REG_SZ) registry key in the Windows' Registry, under HKLM\Software\Oracle\h, where h is the ORACLE_HOME you're targeting. Set this value to the following calculated value (you can calculate this value via the calculator below):
    SETS_PER_POOL = 2 * CPU_COUNT (if VLM is enabled; VLM is enabled by setting USE_INDIRECT_DATA_BUFFERS=TRUE) SETS_PER_POOL = CPU Count / 2 (If VLM is NOT enabled _DB_BLOCK_LRU_LATCHES = (8 * SETS_PER_POOL) AWE_WINDOW_MEMORY (min.) = ((4096 * DB_BLOCK_SIZE * _DB_BLOCK_LRU_LATCHES) / 8) * 1.03125
    So, in a server with 8GB of RAM with 4 CPUs and a DB_BLOCK_SIZE of 8192, the AWE_WINDOW_MEMORY would be ((((2 * 4) * 8) * 4096 * 8192) / 8) * 1.03125 = 276824064.
  4. Set the _DB_BLOCK_LRU_LATCHES DB instance parameter according to the preceding formula.
  5. Set the DB instance parameter use_indirect_data_buffers to TRUE.
  6. Ensure that the DB instance parameter db_cache_size is NOT set.
  7. Set the DB instance parameter db_block_buffers to the following calculated value (you can use the calculator below instead):
    db_block_buffers = (Total RAM - 4GB + AWE_WINDOW_MEMORY) / DB_BLOCK_SIZE
    So, using the preceding example, the db_block_buffers parameter value would be 786432.
  8. Set the DB instance parameter PGA_AGGREGATE_TARGET to ( * 80%) * 40%.
  9. Ensure the DB instance parameter sga_target is NOT set.
  10. Set the DB instance parameter shared_pool_size to AWE_WINDOW_MEMORY * 1.27923, at the very minimum.
  11. Ensure that the streams_pool is NOT set to 0 if you will be using utilities such as the Data Pump ones (e.g., expdp and impdp). 1MB is a good start.
  12. Restart the server and related Oracle services and DB(s).

Note: The CPU count includes hyperthreaded processors, so in a dual-core processor, the CPU count would be 2, not 1.

Set these values:
Is VLM enabled?
CPU_COUNT =
DB_BLOCK_SIZE =
Total RAM =
Results:
SETS_PER_POOL
_DB_BLOCK_LRU_LATCHES =
AWE_WINDOW_MEMORY (min.) =
AWE_WINDOW_MEMORY (rec.) =
DB_BLOCK_BUFFERS =
PGA_AGGREGATE_TARGET (min.) =
PGA_AGGREGATE_TARGET (rec.) =
SHARED_POOL_SIZE (min.) =
SHARED_POOL_SIZE (rec.) =

Thursday, April 10, 2008

Configuring Search for SharePoint Server (MOSS) 2007

  1. Open up the MOSS administration site.
  2. Open up the Shared Services Administration site.
  3. In the Search section, click on Search Settings.
  4. Click on "Default content access account".
  5. Change the account and password to match an account that has access to ALL of the sites and its content.
  6. Click on OK.
  7. Click on Crawl Rules.
  8. If no crawl rules are defined, define them by adding them.
  9. Click on New Crawl Rule.
  10. Enter the full path to the base site collection in the Path field. Append an asterisk (*) at the end of the URL to indicate searching all subsites of this URL.
  11. Select the "Include all items in this path" option.
  12. Click on OK.
  13. Click on "Content sources and crawl schedules".
  14. Click on "Local Office SharePoint Server sites".
  15. In the Crawl Schedules section, click on the Create schedule link under the Full Crawl drop-down list.
  16. Set the options, then click on OK.

Friday, April 04, 2008

Backing up a SharePoint (MOSS) 2007 Site

  1. Setup a writable share with write permissions, specfically granting the SharePoint (MOSS) 2007 server read and write permissions to this share. For example, if the MOSS server is named TEST, grant DOMAIN\TEST$ read and write permissions to this share (where DOMAIN is the domain or workgroup the server belongs to, and TEST$ is the computer's account name on the domain/workgroup). For this example, a share has been setup on the TEST server called MOSSBackup
  2. Open up a command prompt on the MOSS server (cmd).
  3. Navigate to the BIN folder:cd "%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\BIN"
  4. Execute the following command to perform a full backup of the MOSS databases, sites, etc.:stsadm -o backup -backupmethod full -directory \\TEST\MOSSBackup
  5. Add this command to a nightly scheduled task.

Implementing Oracle 10g Data Guard for Standby/Failover Availability

This tutorial demonstrates how to setup Data Guard in the Windows version of Oracle Database 10g. I am assuming you already know how to restart database instances and listeners.

Notes: Oracle Enterprise Manager requires that the database instance it manages be accessible via a Net name. In other words, ensure that a tnsnames.ora file is setup to point to the instance, correctly. DB_UNIQUE_NAME refers to a globally unique name. SERVICE_NAMES refers to one or more service-based names which are registered with the TNS listener. If SERVICE_NAMES is empty, the instance registers with the TNS listener a service name in the following format: DB_UNIQUE_NAME.DB_DOMAIN. Dont' confuse what's in SERVICE_NAMES with a "service name". service names are, typically, Oracle Net names as defined in a tnsnames.ora file, and it's how Oracle Net applications such as SQL*Plus communicate with DB instances. A SID is equivalent to a DB name, or DB_NAME, not a service name, so don't confuse SID with service names either.

Preparing the Source/Primary Database

  1. Login to Oracle Enterprise Manager (typically the shortcut named "Database Control - SID").
  2. Click on Administration.
  3. Click on "All Initialization Parameters".
  4. Ensure that the remote_login_passwordfile parameter is set to "EXCLUSIVE" (without quotes). If it's not, create an exclusive password via the "orapwd" (without quotes) command, then set it. You can set the parameter via an SQL command:ALTER SYSTEM SET remote_login_passwordfile = 'EXCLUSIVE' SCOPE=SPFILE
  5. The DB_NAME parameter must be the same for both the source and target databases. The database name is NOT case sensitive. This is just a note, not anything that needs to be done or set at this point.
  6. The DB_UNIQUE_NAME parameter must be unique for both the source and target databases. If they're not, set them via the Oracle Enterprise Manager. For now, just ensure that the primary/target DB has a unique DB name. Per Oracle, the default value of DB_UNIQUE_NAME is the value of DB_NAME, and DB_UNIQUE_NAME can be up to 30 characters and is case insensitive. The following characters are valid in a database name: alphanumeric characters, underscore (_), number sign (#), and dollar sign ($).
    Alternatively, you can issue the following SQL command:alter system set db_unique_name = 'unique_name' scope=spfileNOTE: Be careful when changing this value. When the SERVICE_NAMES parameter is empty, the instance will register with the TNS listener the DB_UNIQUE_NAME and DB_DOMAN parameters to form a unique, global service name. It's automatically determined. Therefore, BEFORE changing the DB_UNIQUE_NAME, ensure you set the SERVICE_NAMES parameter to include the original service name registered with the TNS listener for this DB instance ALONG with the new DB_UNIQUE_NAME.DB_DOMAIN service name that would've changed. Otherwise, applications such as Oracle Enterprise Manager will not work because they will refer to an service name that no longer exists. So, for example, if the original service name setup for use with OEM was dgtest.dotnetfun.local, and the new DB_UNIQUE_NAME for that DB instance is dgtest_primary, the SERVICE_NAMES parameter would be set to 'dgtest.dotnetfun.local', 'dgtest_primary.dotnetfun.local'.
  7. The SERVICE_NAMES parameter must be unique for both the source and target databases. If they're not, set them via the Oracle Enterprise Manager as specified above. Alternatively, you can use following SQL command:ALTER SYSTEM SET service_names = 'service_name' SCOPE=SPFILENOTE: Again, be careful not to remove the original service name setup for use with Oracle Enterprise Manager, as OEM references the instance this way, and removing it will proably render OEM useless. The default value, per Oracle, is DB_NAME.DB_DOMAIN.
  8. Set the LOG_ARCHIVE_CONFIG parameter to something like this: 'DG_CONFIG=(source_db_unique_name,target_db_unique_name)' (without single quotes, where source_db_unique_name is the unique DB name of the primary DB and target_db_unique_name is the unique DB name of the standby DB. You can do this via Oracle Enterprise Manager or, alternatively, by issuing the following SQL command: ALTER SYSTEM SET log_archive_config = 'DG_CONFIG=(source_db_unique_name,target_db_unique_name)' SCOPE=SPFILE
  9. Set the LOG_ARCHIVE_DEST_1 parameter to point to the source archive log destination, via an SQL command:ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=archive_log_dir VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=db_unique_name' SCOPE=SPFILE
  10. Set the LOG_ARCHIVE_DEST_2 parameter to point to the target archive log destination, via an SQL command:ALTER SYSTEM SET log_archive_dest_2 = 'SERVICE=target_service_name VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=db_unique_name' SCOPE=SPFILE Note that SERVICE here refers to a TNS service name/alias that points to the standby/target DB instance, typically, via a tnsnames.ora service/alias stored on the primary DB.
  11. Set the LOG_ARCHIVE_DEST_STATE_1 and LOG_ARCHIVE_DEST_STATE_2 parameters to ENABLED either via OEM or an SQL command:ALTER SYSTEM SET log_archive_dest_state_1 = "ENABLE" SCOPE=SPFILE; ALTER SYSTEM SET log_archive_dest_state_2 = "ENABLE" SCOPE=SPFILE;
  12. Set the FAL_SERVER parameter to the service name/alias of the source/primary DB, either via OEM or an SQL command:ALTER SYSTEM SET fal_server = 'source_service_name' SCOPE=SPFILE
  13. Set the fal_client parameter to the service name/alias of the target/standby DB, either via OEM or an SQL command:ALTER SYSTEM SET fal_client = 'target_service_name' SCOPE=SPFILE
  14. If the source and target DBs use different DB data file locations/folders, specify both the source and target locations via the db_file_name_convert parameter, either via OEM or an SQL command, starting with the source path, then the target path:ALTER SYSTEM SET db_file_name_convert = 'E:\oracle\product\10.2.0\oradata\Test1\','C:\oracle\product\10.2.0\oradata\test1\' SCOPE=SPFILE
  15. If the source and target DBs use different log file locations/folders (NOT archive log files), specify both the source and target locations via the log_file_name_convert parameter, either via OEM or an SQL command, starting with the source path, then the target path:ALTER SYSTEM SET log_file_name_convert = 'E:\oracle\product\10.2.0\flash_recovery_area\TEST1\ARCHIVELOG','C:\oracle\product\10.2.0\flash_recovery_area\TEST1\ARCHIVELOG' SCOPE=SPFILE
  16. Set the standby_file_management parameter to AUTO, either via OEM or an SQL command:ALTER SYSTEM SET standby_file_management = 'AUTO' SCOPE=SPFILE
  17. If the source database is not already in archive log mode, perform the following SQL commands:shutdown immediate; startup mount; alter database archivelog; alter database open;To test that archiving is working, force a log switch by issuing the following SQL command:ALTER SYSTEM SWITCH LOGFILE;
  18. Perform a cold backup of the source/primary DB's data files. Shutdown the database first, then copy all data files, control files, and online redo log files. After that's done, startup the DB again.
  19. Create a standby control file for the target/standby DB by issuing the following SQL command:alter database create standby controlfile as 'path\test1_mtgvm1.ctl';Replace path with the directory where the control file is to be created.
  20. Create and edit an initialization file for the target/standby DB by issuing the following SQL command:create pfile=path\initSID.ora' from spfile;Replace path with the directory where you want the init file created and SID with the unique DB name of the target/standby DB.
  21. Edit the target/standby init file so that the following parameters apply to the target/standby DB: DB_UNIQUE_NAME, SERVICE_NAMES, CONTROL_FILES, DB_FILE_NAME_CONVERT, LOG_FILE_NAME_CONVERT, LOG_ARCHIVE_DEST_n, INSTANCE_NAME, FAL_SERVER, and FAL_CLIENT. Switch the LOG_ARCHIVE_DEST_n values so that the source and target values are reversed, opposite in order. The same goes for the DB_FILE_NAME_CONVERT and LOG_FILE_NAME_CONVERT values--their values should be switched so that the first path is the standy's and second is the primary's. Ensure that any paths that refer to the local, standby DB are accurate. Ensure that the COMPATIBLE parameter is the same for both the primary and standby databases.

Preparing the Target/Standby Database

  1. Copy the data files, control files, and initialization file to the standby/target server/location, ensuring that they are placed in the proper directories and match paths specified in the initialization file, specifically according to paths defined in the following parameters: CONTROL_FILES, DB_FILE_NAME_CONVERT, LOG_FILE_NAME_CONVERT.

Wednesday, April 02, 2008

ORA-02156, ORA-00911, and other Oracle Errors During Database Configuration Assistant Creation of Database

If you get ORA-02156, ORA-00911, and other Oracle errors during a database creation process via the Database Configuration Assistant, it's most likely due to an account password that contains odd characters, such as spaces and other non-alpha-numeric characters.

Choose a typical alpha-numeric password, then change it once accounts and databases have been created.

Thursday, March 27, 2008

Mirroring Databases in SQL Server 2005

Introduction

This tutorial will show you how to mirror one database from one instance of SQL Server 2005 to another. I will be using the AdventureWorks database for this demonstration and will not be using a Witness server (only a Principal and Mirror server [i.e., Source and Target]).

Please note that both the Principal and Mirror servers must be of the same SQL Server edition. If they are not, mirroring will not work.

Enable Mirroring in SQL Server 2005 if SP1 is Not Installed

On computer/instance mirror A:

  1. Open the SQL Server Configuration Manager for SQL Server 2005, typically, this is located in the Programs menu of the Start button (Microsoft SQL Server 2005, then Configuration Tools).
  2. Select the SQL Server 2005 Services node.
  3. In the right pane, right-click on the SQL Server service, then click on Properties.
    SQL Server Configuration Manager for SQL Server 2005
  4. Click on the Advanced tab.
  5. Locate the Startup Parameters field, then append trace flag 1400 to it: ; -T 1400
  6. Right-click on the SQL Server service, then click on either Restart or Start.

On computer/instance mirror B:

  1. Repeat the steps outlined for On computer/instance mirror A for this computer.

Please note mirroring doesn't seem to work if you use this trace flag with SQL Server 2005 without any Service Packs installed. The trace flag seems to work ONLY with older RTM versions. So, if you have SQL Server 2005 with no Service Packs installed, please install them on all running instances.

Preparing Databases for Mirroring

  1. Using SSMS (SQL Server Management Studio), set the Recovery Model of the source database to Full, if it's not already.
  2. Backup the source database AND transaction log(s), a full backup first, then a transaction log(s) backup.
  3. Restore the just-backed up source database AND transaction log(s) to the target server/instance using the WITH NORECOVERY option for each restore(s), starting with the full database restore, then transaction log(s) restore(s), ensuring that the data file paths are not physically the same (i.e., do not overwrite the source data files with this restore).

Configuring and Starting Mirroring

  1. Using SSMS, launch the Mirror... task on the source database.
  2. Click on the Configure Security... button.
  3. Click on Next.
  4. Select No to NOT include a witness server.
  5. Click on Next.
  6. Click on Next to save the security configuration.
  7. Select the source server, which should already be selected, in the Principal server instance field, set or leave the port, then specify a unique Endpoint name.
  8. Click on Next.
  9. Select the target server in the Mirror server instance field, set or leave the port, then specify a unique Endpoint name.
  10. Click on Next.
  11. Set the Principal and Mirror Service Accounts, preferrably, they will be the same account.
  12. Click on Next.
  13. Click on Finish.

    If you run into problems, re-click on the Configure Security button to change the parameters. You should get Successful results for both Endpoints.
  14. Click on Do Not Start Mirroring.
  15. Start mirroring by clicking on the Start Mirroring button. If successfull, the Pause button should be enabled.

Using the Database Mirroring Monitor

  1. In SSMS, right-click on the source database, navigate to Tasks, then click on Launch Database Mirroring Monitor...
  2. Click on Register mirrored database.
  3. Click on the Connect button, then select the Mirror/target server.
  4. Click on the Register checkbox in the Mirrored databases list.
  5. Click on OK.
  6. In the left pane, expand the Database Mirroring Monitor node by clicking on the plus sign.
  7. Click on the mirrored database. You should now see the status of the mirror.

Failing Over to the Mirrored/Target Database

  1. Execute the following T-SQL command at the mirror:ALTER DATABASE AdventureWorks SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS

Issues to Consider About Database Mirroring and this Tutorial

  1. The source/Principal and target/Mirror SQL Server Service account(s) must be granted CONNECT permission on the target/Mirror and source/Principal servers respectively. If not, mirroring will fail upon start.
  2. Encryption - By default, data is encrypted, sent to the mirror, then decrypted. This uses up more server resources and bandwidth than it would without encryption. So, ONLY use encryption if the data being mirrored is sensitive and should be encrypted.
  3. Witness - This tutorial doesn't use a Witness server. A witness server can provided automated failover capabilities.
  4. Asynchronous mirroring is only available in SQL Server 2005 Enterprise & Developer Editions, Synchronous mirroring is available in all others, except for Express Edition. So, fully evaluate the performance implications when using mirroring with SQL Server 2005 Standard Edition, as performance might be negatively impacted in a production environment.

Monday, March 24, 2008

Business Data Catalog Definition Editor Installation Error 'SetParent failed for Database'

If you get a 'SetParent failed for Database' error during the installation of the Microsoft Business Data Catalog Definition Editor, allow remote connections to the local SQL Server 2005 Express Edition server:

  1. Start the "SQL Server Surface Area Configuration" application.
  2. Click on "Surface Area Configuration for Services and Connections".
  3. Under Database Engine, select Remote Connections.
  4. Select "Local and remote connections".
  5. Click on OK.
  6. Close the application.
  7. Retry the BDC Editor installation.

Wednesday, March 19, 2008

Displaying External Web Services Data in SharePoint Server 2007

Prerequisites

  • SharePoint Server 2007 (MOSS 2007) Enterprise Edition
  • SharePoint Server 2007 SDK v1.3 or newer

Building the Application Definition File

  1. If you haven't already installed the BDC Definition Editor, install it. It should be located here: "%ProgramFiles%\2007 Office System Developer Resources\Tools\BDC Definition Editor". Just launch the setup.exe program to install it.
  2. From the Programs menu, startup the Microsoft ® Business Data Catalog Definition Editor.
  3. Click on "Add LOB SYstem".
  4. Click on "Connect to Webservice".
  5. Enter the following Web Service URL in the Url field: http://ws.cisa.ca/WehireWS/JobsWs.asmx?WSDL.
  6. Click on Connect.
  7. Click on the "Add Web Method" side-button.
  8. Drag the GetJobsByTitle method onto the Design area.
  9. Call the LOB System Name "JobsWesternCanadaWebService" (without quotes).
  10. In the Metadata Objecta pane, click on the JobsWesternCanadaWebService system.
  11. In the Properties pane, set the WildcardCharacter field to "$" (without quotes).
  12. Ensure that that WsdlAuthenticationMode is set to PassThrough.
  13. Set the DefaultDisplayName to "Jobs in Western Canada Web Service" (without quotes).
  14. In the Metadata Objects pane, expand the Entities node, then click on Entity0.
  15. In the Properties pane, set the Title to "Jobs in Western Canada" (without quotes).
  16. Set the Name property to "JobsWesternCanada" (without quotes).
  17. Set the DefaultDisplayName to "Jobs in Western Canada" (without quotes).
  18. In the Metadata Objects pane, right-click on the Identifiers node, then click on Add Identifier.
  19. In the Properties pane, set the Name to "Title" (without quotes).
  20. In the Metadata Objects pane, locate the GetJobsByTitle method, then locate the title parameter.
  21. Expand the title parameter's nodes until you reach the Item node, then select it.
  22. In the Properties pane, set the Identifier property to Title[JobsWesternCanada].
  23. Set the name property to "Title" (without quotes).
  24. In the Metadata Objects pane, expand the Return parameter's nodes until you reach the Item node, then click on the Title node.
  25. In the Properties pane, set the Identifier property to Title[JobsWesternCanada].
  26. In the Metadata Objects pane, locate the Filters node of the GetJobsByTitle method.
  27. Right-click on the Filters node, then click on Add Filter.
  28. In the Properties pane, set the Name to "TitleEqualsFilter" (without quotes).
  29. Set the DefaultDisplayName to "Title" (without quotes).
  30. Set the FilterType to Equals.
  31. In the Metadata Objects pane, locate and expand the last title parameter node of the GetJobsByTitle method, then select it.
  32. In the Properties pane, set the FilterDescriptor to TitleEqualsFilter.
  33. In the Metadata Objects pane, right-click on the Instances node of the GetJobsByTitle method, then click on Add Method Instance.
  34. Select Association as the Method Instance Type.
  35. In the Source Entities pane, set the entity to JobsWesternCanada.
  36. Click on OK.
  37. In the Properties pane, set the Name property to "GetJobsByTitleAssociationInstance" (without quotes).
  38. In the Metadata Objects pane, right-click on the Instances node of the GetJobsByTitle method, then click on Add Method Instance.
  39. Select Finder as the Method Instance Type.
  40. Click on OK.
  41. In the Properties pane, set the Name to "GetJobsByTitleFinderInstance" (without quotes).
  42. Test to ensure the Finder method works by a) right-clicking on the GetJobsByTitleFinderInstance method, b) clicking on Execute, c) entering ".NET Web Developer" (without quotes) in the Value field, d) then clicking on the Execute button. You should get results back from the web service. Close the test form.
  43. In the Metadata Objects pane, select the JobsWesternCanadaWebService LOB system.
  44. Click on the Export button, then save the file as "JobsWesternCanadaWebService.xml" (without quotes).

Importing the BDC Definition File

  1. Open up the SharePoint 3.0 Central Administration web page.
  2. Under Shared Services Administration, click on the shared service listed.
  3. Under Business Data Catalog, click on "Import application definition".
  4. Click on the Browse button, then locate and open the JobsWesternCanadaWebService.xml file.
  5. Click on Import.
  6. You should've gotten a success message. Click on OK.
  7. Click on Manage Permissions.
  8. Add the users/groups you'd like to grant permission to execute the LOB system.

Displaying the Web Service Data via a Business Data List

  1. In the SharePoint Server 2007 site, navigate to a web part page where you'd like to see the web service in action.
  2. Click on Site Actions, then Edit Page.
  3. Click on "Add a Web Part".
  4. Expand the "All Web Parts" node.
  5. Under Business Data, check the "Business Data List" web part.
  6. Click on Add.
  7. Click on Edit in the "Business Data List" web part, then click on "Modify shared web part".
  8. Click on the Browse icon, next to the Type field.
  9. Select JobsWesternCanadaWebService_Instance, then click on OK.
  10. Click on the Apply button.
  11. Click on the OK button.
  12. Click on the Publish button, if necessary, to save the page changes.
  13. In the "Jobs in Western Canada List" web part, enter ".NET Web Developer" (without quotes) in the "Title is equal to" field.
  14. Click on Retrieve Data. As of March 23, 2008, there is one result listed.