Get my Web service to read set Tables and db from config

danjamandanjaman Posts: 12
edited July 12, 2007 2:23PM in SQL Toolkit Previous Versions
I want to be aboe to set my Datasource (DB) to read from my Web.config file as Connection strings.

I want to also be able to pass a webthod of parameter, be selecting a group that contains a set number of tables from my db.

This way we can set migration to run only on that group og tables. See my Web Service below:

using System;
using System.Data;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Xsl;
using System.Text;
using System.Reflection;
using System.Diagnostics; // for ProcessStartInfo
using RedGate.SQL.Shared;
using RedGate.SQLCompare.Engine;
using RedGate.SQLDataCompare.Engine;


namespace SQLDataCompareWebService
{

public struct ClientData
{
public String Name;
public int ID;
}
/// <summary>
/// Summary description for WebService1.
/// </summary>
[WebService(Namespace = "http://localhost/SQLCompareWebService/",
Description="This is a schema/data WebService.")]
public class SQLCompareWebService1 : System.Web.Services.WebService
{
private const int CacheTime = 1000000; // seconds

public SQLCompareWebService1()
{
//CODEGEN: This call is required by the ASP+ Web Services Designer
InitializeComponent();
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
}


//To build, uncomment the following lines then save and build the project
//
[WebMethod]
public void DataMigration()
{
Database db1 = new Database();
Database db2 = new Database();
try
{
db1.Register(new ConnectionProperties("nse-develop22", "WidgetDev"), Options.Default);
db2.Register(new ConnectionProperties("nse-develop22", "WidgetLive"), Options.Default);
}
catch (System.Data.SqlClient.SqlException sqe)
{
Console.WriteLine("SQL Exception: " + sqe.Message);
return;
}
Differences diffs = db1.CompareWith(db2, Options.Default);
Work w = new Work();
w.BuildFromDifferences(diffs, Options.Default, true);
//Uncomment next line to get schema migration script
string schemaSQL=w.ExecutionBlock.GetString();
//Uncomment the next lines to run migration script
BlockExecutor be=new BlockExecutor();
be.ExecuteBlock(w.ExecutionBlock, "nse-develop22", "WidgetDev");

db1.Dispose();
db2.Dispose();

Database ddb1 = new Database();
Database ddb2 = new Database();
ddb1.RegisterForDataCompare(new ConnectionProperties("nse-develop22", "WidgetDev"), Options.Default);
ddb2.RegisterForDataCompare(new ConnectionProperties("nse-develop22", "WidgetLive"), Options.Default);

ComparisonSession session = new ComparisonSession();
TableMappings mappings = new TableMappings();
mappings.CreateMappings(ddb1.Tables, ddb2.Tables);
session.CompareDatabases(ddb1, ddb2, mappings);








SqlProvider provider = new SqlProvider();
ExecutionBlock ebData = provider.GetMigrationSQL(session, true);




//we want to run the SQL on WM so pass in true as the second parameter
ExecutionBlock block = provider.GetMigrationSQL(session, true);
Console.WriteLine("Migration SQL:");
Console.WriteLine(block.GetString());

BlockExecutor executor = new BlockExecutor();
executor.ExecuteBlock(block, "nse-develop22", "WidgetLive");

session.Dispose();
block.Dispose();
db1.Dispose();
db2.Dispose();
}





}
}

Comments

  • Brian DonahueBrian Donahue Posts: 6,590 New member
    I've got something that may help... Given an XML document with the following schema:
    &lt;?xml version="1.0" encoding="utf-8" ?&gt; 
    &lt;database server="." name="WidgetDev"&gt;
    &lt;data&gt;
    	&lt;table name="table name"&gt;
    		&lt;comparisonkeycolumn name="ID column" /&gt;
                                    &lt;whereclause&gt;something &lt; some number&lt;/whereclause&gt;
    		&lt;columns&gt;
    			&lt;column name="column name" /&gt;
    		&lt;/columns&gt;
    	&lt;/table&gt;
    &lt;/data&gt;
    &lt;/database&gt;
    
    you can specify a list of tables and columns to add to a project. The following code will turn this into an array of objects:
    using System;
    using System.Xml;
    using System.Reflection;
    using System.IO;
    using System.Collections;
    
    namespace ConfigTest
    &#123;
    	/// &lt;summary&gt;
    	/// Summary description for ConfigReader.
    	/// &lt;/summary&gt;
    	public class ConfigReader
    	&#123;
    		private XmlDocument doc=null;
    			public ConfigReader&#40;&#41; 
    		&#123;
    			
    			Stream stm=new StreamReader&#40;"Web.config"&#41;;
    			XmlTextReader reader=new XmlTextReader&#40;stm&#41;;
    			doc=new XmlDocument&#40;&#41;;
    			doc.Load&#40;reader&#41;;
    		&#125;
    		public Hashtable GetDataObjects&#40;&#41;
    		&#123;
    			System.Xml.XmlNode dataNode=doc.SelectSingleNode&#40;"/database/data"&#41;;
    			Hashtable dataTables=new Hashtable&#40;&#41;;
    			
    			foreach &#40;XmlNode n in dataNode.ChildNodes&#41;
    			&#123;
    				DataObject o = new DataObject&#40;&#41;;
    				o.FullyQualifiedName=n.Attributes&#91;"name"&#93;.Value;
    				if &#40;n&#91;"comparisonkeycolumn"&#93;!=null&#41; o.ComparisonKeyColumn=n&#91;"comparisonkeycolumn"&#93;.Attributes&#91;"name"&#93;.Value;
    				if &#40;n&#91;"whereclause"&#93;!=null&#41; o.WhereClause=n&#91;"whereclause"&#93;.InnerText;
    				foreach &#40;XmlNode column in n&#91;"columns"&#93;&#41; 
    				&#123;
    					o.IncludedColumns.Add&#40;column.Attributes&#91;"name"&#93;.Value&#41;;
    				&#125;
    				dataTables.Add&#40;n.Attributes&#91;"name"&#93;.Value,o&#41;;
    			&#125;
    		return dataTables;
    		&#125;
    		public string GetSqlServerName&#40;&#41;
    		&#123;
    		System.Xml.XmlNode schemaNode=doc.SelectSingleNode&#40;"/database"&#41;;
    		return schemaNode.Attributes&#91;"server"&#93;.Value;
    		&#125;
    		public string GetSqlDatabaseName&#40;&#41; 
    		&#123;
    			System.Xml.XmlNode schemaNode=doc.SelectSingleNode&#40;"/database"&#41;;
    			return schemaNode.Attributes&#91;"name"&#93;.Value;
    		&#125;
    	&#125;
    &#125;
    
    The class describing the object:
    using System;
    using System.Collections;
    
    namespace ConfigTest
    &#123;
    	/// &lt;summary&gt;
    	/// An object describing attributes of a table or view
    	/// &lt;/summary&gt;
    	public class DataObject
    	&#123;
    		private string comparisonKeyName=null;
    		private string whereClause=null;
    		private ArrayList includedColumns = new ArrayList&#40;&#41;;
    		private string fullyQualifiedName=null;
    		public DataObject&#40;&#41;
    		&#123;
    			
    		&#125;
    		public string FullyQualifiedName
    		&#123;
    			get 
    			&#123;
    				return fullyQualifiedName;
    			&#125;
    			set 
    			&#123;
    				fullyQualifiedName=value;
    			&#125;
    		&#125;
    		public string ComparisonKeyColumn 
    		&#123;
    			get &#123;
    				return comparisonKeyName;
    				&#125;
    			set &#123;
    				comparisonKeyName=value;
    				// The comparison key absolutely needs to be in the collection of columns!
    				if &#40;!includedColumns.Contains&#40;value&#41;&#41; includedColumns.Add&#40;value&#41;;
    			&#125;
    		&#125;
    		public string WhereClause 
    		&#123;
    			get &#123;
    				return whereClause;
    			&#125;
    			set &#123;
    				whereClause=value;
    			&#125;
    		&#125;
    		public ArrayList IncludedColumns
    		&#123;
    			get &#123;
    				return includedColumns;
    			&#125;
    			set &#123;
    				// Prevent someone from adding this twice
    				if &#40;!includedColumns.Contains&#40;value&#41;&#41; includedColumns.Add&#40;value&#41;;
    			&#125;
    		&#125;
    	&#125;
    &#125;
    
    And finally the code to read the information and compare the data:
    private static void SetDataExecutionBlock&#40;string serverName, string databaseName,  Hashtable selectedTables, Options schemaOptions, EngineDataCompareOptions dataOptions&#41;
    		&#123;			
    			Database database = new RedGate.SQLCompare.Engine.Database&#40;&#41;;
    			try 
    			&#123;
    				//Register database for Data Compare
    				database.RegisterForDataCompare&#40;new ConnectionProperties&#40;serverName, databaseName&#41;, schemaOptions&#41;;
    				using &#40;ComparisonSession session = new ComparisonSession&#40;&#41;&#41;
    				&#123;
    					TableMappings tableMappings = new TableMappings&#40;&#41;;	
    
    					tableMappings.Options = dataOptions;
    					//
    					// Create the mappings. &#40;Nb. only want tables. should not package data in views
    					//
    					tableMappings.CreateMappings&#40;database.Tables, null&#41;;
    					
    					foreach &#40;TableMapping m in tableMappings&#41; 
    					&#123;
    						if &#40;selectedTables.ContainsKey&#40;m.Obj1.FullyQualifiedName&#41;&#41;
    						&#123;
    							DataObject o=&#40;DataObject&#41;selectedTables&#91;m.Obj1.FullyQualifiedName&#93;;
    							m.MatchingMappings.Clear&#40;&#41;;
    							m.MatchingMappings.Add&#40;m.FieldMappings&#91;o.ComparisonKeyColumn&#93;&#41;;
    
    							foreach &#40;FieldMapping f in m.FieldMappings&#41; 
    							&#123;
    								f.Include=false;
    							&#125;
    							foreach &#40;FieldMapping f in m.FieldMappings&#41; 
    							&#123;
    								if &#40;o.IncludedColumns.Contains&#40;f.Obj1.FullyQualifiedName&#41;&#41; f.Include=true;
    							&#125;
    							if &#40;o.WhereClause!=null&#41; m.Where=new WhereClause&#40;o.WhereClause&#41;;
    
    						&#125;
    						else m.Include=false;
    						m.RefreshMappingStatus&#40;&#41;;
    					&#125;
    					
    					session.Options = dataOptions;					
    					session.CompareDatabases&#40;database, null, tableMappings&#41;;
    			
    					SqlProvider provider = new RedGate.SQLDataCompare.Engine.SqlProvider&#40;&#41;;
    					provider.Options = dataOptions;
    					
    					try
    					&#123;
    						provider.GetMigrationSQL&#40;session, true&#41;;
    					&#125;
    					finally
    					&#123;
    						//m_DataBlock = provider.Block;	//Always set the DataBlock because above code could
    						// throw an exception
    					&#125;					
    					//GetDataMessages&#40;provider&#41;;			//Go into the provider and get data messages etc...
    				&#125;				
    			&#125;
    			finally
    			&#123;
    				database.Dispose&#40;&#41;;
    			&#125;
    			return ;
    		&#125;
    
  • I want this to show up in my WebService as a Method:
    I have written it as
                &#91;WebMethod&#93;
                public void SetSchemaDataMigration&#40;string sourceServer, string sourceServerDBName, Hashtable selectedTables, Options schemaOptions, EngineDataCompareOptions dataOptions&#41;
                &#123;
                       Database database = new RedGate.SQLCompare.Engine.Database&#40;&#41;;
                    try
                    &#123;
    

    But I need it to look like
            &#91;WebMethod&#93;
            public void TotalSchemaDataMigration&#40;&#41;
            &#123;
                Database db1 = new Database&#40;&#41;;
                Database db2 = new Database&#40;&#41;;
    
    
                try
                &#123;
    

    Where I can select it as an option in my webService.
    Is this correct or wrong
                &#91;WebMethod&#93;
                public void SetSchemaDataMigration&#40;&#41;
                &#123;
                       Database database = new Database&#40;&#41;;
                       Hashtable selectedTables =  new Hashtable &#40;&#41;;
                       EngineDataCompareOptions dataOptions = new dataOptions&#40;&#41;;
                    try
                    &#123;
                        //Register database for Data Compare 
                         Database.Register&#40;new ConnectionProperties&#40;_sourceServerName, _sourceDBName&#41;, Options.schemaOptions&#41;;
                        using &#40;ComparisonSession session = new ComparisonSession&#40;&#41;&#41;
    
  • Brian DonahueBrian Donahue Posts: 6,590 New member
    edited July 12, 2007 8:28AM
    I'm sorry but I don't understand. You want to specify tables from the webservice client-end by setting a property on the webservice?

    I thought you wanted to specify the tables in web.config? This would be done at the server end...
  • I used the XMLconfig reader you wrote, it appears to work.
    Here is my problem, I want to use the setting configurationManager to handle the setting in my config file.

    then I want to parameterize my Tables by there group name into a webmethod.

    How would I accomplish this.

    PLEASE HELP.
  • Brian DonahueBrian Donahue Posts: 6,590 New member
    You mean that you want to use some object from the System.Configuration namespace to read Web.config instead of reading it manually with an XmlTextReader?
  • Want I want to do is nor use XMLReader, but use configuration manger to read the setting form the config file:

    the database, server, tha tables, etc. then pass them through as parameters so they can be selected.

    they will be entered into the config file manually but will need to be read using configurationManager.

    Is my purpose clear. the code you setup works, but it uses XMLreader, I want to use configurationManager and pass thouse setting off as parameters to allow web service to take those parameters and set them.

    So they can select a set Group, from a selected Database, to migrate to second DB.

    Is this clear.
  • Brian DonahueBrian Donahue Posts: 6,590 New member
    I see. It looks like the ConfigurationManager object is new to .NET 2.0. I hadn't done much web development in this version. Maybe the information on ConfigurationSections from Microsoft will help...

    http://msdn2.microsoft.com/en-us/library/system.configuration.sectioninformation(VS.80).aspx
  • If I use the XMLcofgireader.

    how would I pass it as parameters so it can know which group and which tables are selected form that group.

    Thanks
Sign In or Register to comment.