What the system offers for free
As I explained in previous post, .NET is very XML friendly, so it gives us a few base functionalities to avoid us doing things already done, here we say it saves us from inventing hot water. To demostrate the basic functionalities I build a simple, fundamentally useless class that demonstrates us how the basic data types of .NET are all serializable.
using System;
using System.Text;
namespace DnwEnitities.Entities
{
public class Serializzabile
{
public Serializzabile()
{
TheChar = 'A';
TheByte = 10;
TheBool = true;
TheShort = 100;
TheInt = 1000;
TheLong = 1000000;
TheFloat = 1234.7899f;
TheDouble = 9800000.89600;
TheDecimal = 766000000.654390001m;
TheString = "The string is very nice and useful.";
TheDate = DateTime.Now;
TheGuid = Guid.NewGuid();
TheEnum = SerializableEnum.ALot;
}
public char TheChar
{
get;
set;
}
public byte TheByte
{
get;
set;
}
public bool TheBool
{
get;
set;
}
public short TheShort
{
get;
set;
}
public int TheInt
{
get;
set;
}
public long TheLong
{
get;
set;
}
public float TheFloat
{
get;
set;
}
public double TheDouble
{
get;
set;
}
public decimal TheDecimal
{
get;
set;
}
public string TheString
{
get;
set;
}
public DateTime TheDate
{
get;
set;
}
public Guid TheGuid
{
get;
set;
}
public SerializableEnum TheEnum
{
get;
set;
}
public static Serializzabile ReadXml(string pSerializedData, bool pIsXmlData)
{
Serializzabile retP = null;
if (!pIsXmlData)
{
retP = (Serializzabile)SerializeHelper.DeserializeFromFile(
typeof(Serializzabile), pSerializedData);
}
else
{
retP = (Serializzabile)SerializeHelper.DeserializeFromString(
typeof(Serializzabile), pSerializedData);
}
return (retP);
}
public virtual void WriteXml(string pFileName)
{
SerializeHelper.SerializeToFile(pFileName, this, typeof(Serializzabile), false, string.Empty);
}
public virtual string WriteXml()
{
return (SerializeHelper.SerializeToString(this, false, string.Empty));
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Char: {0}", this.TheChar);
sb.AppendLine();
sb.AppendFormat("Byte: {0}", this.TheByte);
sb.AppendLine();
sb.AppendFormat("Bool: {0}", this.TheBool);
sb.AppendLine();
sb.AppendFormat("Short: {0}", this.TheShort);
sb.AppendLine();
sb.AppendFormat("Int: {0}", this.TheInt);
sb.AppendLine();
sb.AppendFormat("Long: {0}", this.TheLong);
sb.AppendLine();
sb.AppendFormat("Float: {0}", this.TheFloat);
sb.AppendLine();
sb.AppendFormat("Double: {0}", this.TheDouble);
sb.AppendLine();
sb.AppendFormat("Decimal: {0}", this.TheDecimal);
sb.AppendLine();
sb.AppendFormat("String: {0}", this.TheString);
sb.AppendLine();
sb.AppendFormat("Date: {0}", this.TheDate);
sb.AppendLine();
sb.AppendFormat("Guid: {0}", this.TheGuid);
sb.AppendLine();
sb.AppendFormat("Enum: {0}", this.TheEnum);
sb.AppendLine();
return (sb.ToString());
}
}
public enum SerializableEnum : int
{
None = 0,
All,
Some,
ALot
}
}
This class represents the most raw and simple entity, it contains some public properties, one for each of the base data in .NET, it contains the WriteXml and ReadXml methods, using our Helper to write and read in XML the content of the class and an override of the ToString method that helps us visualize the class contents. There is also a simple Enumeration, showing us that enumerable values are serialized automatically.
Instantiating a class of Serializzabile type, and calling its WriteXml method to write its content to a file, the content of the file is the
following:
<?xml version="1.0" encoding="utf-8"?>
<Serializzabile xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TheChar>65</TheChar>
<TheByte>10</TheByte>
<TheBool>true</TheBool>
<TheShort>100</TheShort>
<TheInt>1000</TheInt>
<TheLong>1000000</TheLong>
<TheFloat>1234.78992</TheFloat>
<TheDouble>9800000.896</TheDouble>
<TheDecimal>766000000.654390001</TheDecimal>
<TheString>The string is very nice and useful.</TheString>
<TheDate>2010-11-01T09:26:13.331+01:00</TheDate>
<TheGuid>3da90b04-ec02-4308-a177-fc6723ab8aa9</TheGuid>
<TheEnum>ALot</TheEnum>
</Serializzabile>
Using the ReadXml to re-read the class, we will obtain an equivalent object. If we haven’t any particular requirement to satisfy in our programs, this is the simplest way to build a serializable entity.
This is the list of what we did a couple of weeks ago in my organization, moving our development TFS from a domain to another domain, I write it here in case someone else needs it and of course to find it out if I ever need this again.
First thing to do is read carefully the TFS documentation on this matter, starting with the MSDN document titled Move Team Foundation Server from One Environment to Another and reading carefully what to do in your specific case. Our move was the simplest one, We needed to move Our Single Server from domain XXX to domain YYY without changing anything.
The first thing we did was a full backup of all the TFS databases from our SQL Server 2008. Then, we did a Ghost of the Server Hard Disk, to be sure to have the possibility to Rollback in case of problems.
Then the procedure we followed was this:
- We created the same service users we had on our present environment on the new domain, this means, the TfsService user, the SQLService user, the Proxy User and other domain users required by the system and we give them the same passwords.
- We opened the TFS configuration and write down on a notepad all user groups and all TFS groups and WIndows groups and users mapped to every TFS project inside our server paying attention to write down everything. This operation is important because the Group and User mapping on project will be cleared during the moving and to avoid developers from “Screaming” and “cursing you” because they’ve lost access to their projects you have to be careful on this.
- Another important thing to remember is DO NOT CHANGE THE NAME OF THE SERVER IN THE NEW ENVIRONMENT this is Very Important, because SQL Server 2008 has some problems when you rename its instance under it’s nose. So if you change the servers naming in the new domain, for your sake, move your old servers with the same name and let them Die with that name.
- After this, You have to kill the TFS services, you can do that using the TFSServiceControl command line utilities which is located under the Tools folder of the TFS 2010 installation folder.
TfsServiceControl quiesce
is the command to shut down the services.
- You also have to shut down IIS if you have sharepoint on the same machine and SQL Server services.
- Now you have to move the server to the new domain, Remember to activate a local system Administrator User with a simple password, use a domain administrator with the rights to do so to remove the server from the old domain. Restart it, verify that the services are still stopped or stop them again using the local Administrator.
- Remember also to activate the SA user with a password you know or to create a SQL Server user with SysAdmin rights giving it a password of your choice.
- Join the server to the new domain. Change the Service users for SQL Server and TFS services to the one in the new domain and start SQL Server, do not yet start TFS.
- Then you first need to open the SQL Server Management Studio and log on using SA or your personal Sysadmin, go to the Security folder and verify that local machine Windows Groups have mantained their rights. Then map the new domain Windows Groups or users you had on the old domain and assign them rights and roles on the TFS databases. Remove database mappings from the old users before deleting them.
- You also need to go to the Users management of the local Server, and if you created local groups containing domain users or groups, you need to remap the users and groups from the new domain.
- Then you need to use the Identities Command, which is one of the options provided by the TFSConfig command line utility of TFS to change inside the configuration database of TFS the SIDs of the Domain Users used to run TFS Services, the utility stays on the Tools folder of the TFS installation. There is an article on the msdn linked to the guide I linked at the beginning of this article that gives you all the informations on how to use it. The command is something like:
TFSConfig Identities /change /fromdomain:olddomain /todomain:newdomain /account:accountname /toaccount:accountname
/sqlinstance:sqlserverinstancename /databasename:TfsConfigDatabase /account:sqlaccountname
If you Kept instance names and user names and passwords identical on the two domains this is a simple routine operation and all works at first shot. So keep clearly in mind, no Server name change, no service user change, no password change.
- In the unfortunate case you had to change a service user, there is another command of the TFSConfig utility, named Accounts, you can use to specify to TFS the new service accounts before executing the Identities command.
- After this you can restart TFS using the TfsServiceControl unquiesce command.
- Open the TFS configuration manager, go back to the User Access and permission configuration and restore for each project the Windows Users and groups and the TFS users and Groups that have been erased by the domain move. With a particular care for the Project collection valid users, Team Foundation Licensed Users whicy you find if your first installation was a Workgroup TFS is no more needed.
After this procedures are completed, you can open a Visual Studio 2010 and attach to the TFS client from a computer in the new domain, if you did all well, the server will respond exactly as it responded on the old domain.
I didn’t speak of Sharepoint, well we are a small team and don’t use sharepoint, but the migration guide gives you all the instruction to migrate also Sharepoint services, so I’m sure it works correctly.