|
|
Software Engineer - Red Gate Software
Engine programmer and factotum.
-
Posted Thursday, May 22, 2008 8:36 AM |
|
What I learned lately - by Richard Mitchell Aged 32 3/4.
1. When you're managing a large project team don't expect to get 4 days coding done a week. 2. Designing a UI that people can use is much harder than it seems. 3. Hire the right people and they'll work wonders. 4. I can't pronounce Hungarian names. 5. Or French ones. 6. And I get English ones wrong (Clive is pronounced Colin in my head) 7. Foam dart guns are fun. 8. Splitting work into components allows multiple developers to just get on with it. 9. Setting up test systems is a hair-pulling screaming experience that is more likely than anything else to make somebody go postal (see 7). 10. My team are wunnerful.
|
-
Posted Thursday, February 21, 2008 9:04 AM |
As I've been doing a bit of work on remoting (see my previous blog post) I'm necessarily looking quite a bit into the serialization of messages. Yesterday I found quite a good article on the CodeProject website with a good set of references about remoting it's well worth a read. While I'm on the subject I thought I'd share my variation of Ingo Rammer's RemotingHelper class. This is a class that enables you to create remote classes based on interfaces via the remoting configuration file. Normally you would have to use a call to Activator.GetObject() and that takes URL so suddenly all of your configuration has to be done outside the easy to edit config file. The only issues I had with the Ingo's RemotingHelper class was that it was very fussy over the type of the remoting object so if the version changed it would stop working. To rectify that issue for my case I only store the FullName in the lookup table. This makes it a lot easier when getting auto-versioned builds from our build system (we have two build computers, one called Bob and the other called Wendy - guess why) so I don't have to change both the client and server every single time.
/// <summary> /// Use Interface-based remote objects with config files /// http://www.thinktecture.com/resourcearchive /// /net-remoting-faq/useinterfaceswithconfigfiles /// </summary> public class RemotingHelper { private static bool m_IsInit; private static Dictionary<string, WellKnownClientTypeEntry> m_WellKnownTypes;
/// <summary> /// Replacement to Activator.GetObject which allows config files /// to work properly /// </summary> /// <param name="type">Type to create</param> /// <returns>Type created</returns> public static Object GetObject(Type type) { if (!m_IsInit) { InitTypeCache(); }
WellKnownClientTypeEntry entr;
if (!m_WellKnownTypes.TryGetValue(type.FullName, out entr)) { throw new RemotingException("Type not found!"); }
return Activator.GetObject(entr.ObjectType, entr.ObjectUrl); }
private static void InitTypeCache() { m_IsInit = true; m_WellKnownTypes = new Dictionary<string, WellKnownClientTypeEntry>(); foreach (WellKnownClientTypeEntry entr in RemotingConfiguration.GetRegisteredWellKnownClientTypes()) {
if (entr.ObjectType == null) { throw new RemotingException("A configured type could not " + "be found. Please check spelling"); } m_WellKnownTypes.Add(entr.ObjectType.FullName, entr); } } }
This only really works because the FullName is likely to be pretty unique and will change a lot less often than the Type information which changes every build due to the version increments. The actual purpose of this blog at the start was to mention a lovely little thing I stumbled across while looking for solutions to the Shared version mismatch remoting calls was to do with serializing classes for persistence. Again if you serialize something to disk it's all good you can load it up again no problems. Unless the version of your strongly named assembly changes version at which point suddenly it stops working. The simple solution that seems to work is....
BinaryFormatter formatter = new BinaryFormatter(); formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
Now when deserializing the runtime now no longer has to find the perfect match for the assembly - just something that is 'close enough' will do - lovely jubbly.
|
-
Posted Tuesday, February 12, 2008 9:42 AM |
I've been playing a bit lately with .NET Remoting and I must say that so far I'm deeply un-impressed. The documentation seems to be sparse at best and downright misleading at worst. So I thought I'd put a few of my discoveries here so that people can learn from my mistakes.
.NET Remoting is a technology that allows the .NET runtime to code in another AppDomain or even another remote machine without having to worry about the details. At least that's the theory. The problem is when you want to make calls that rely on custom classes or have a shared base class but different concrete implementations of that class on client and server side.
Normally I'd just use an interface and be done with it. That sounds easy right? We'll have a nice interface in our common area and then client and server can implement the interface and it'll all be good. To a certain value of work this will work although it's not as neat as it could be and passing classes that can be subclassed around via the interface can get painful as you'll see later.
Shared: using System.Runtime.Serialization;
namespace RedGate.Common { public interface IFruit { string GetName(); string GetTree(Tree tree); }
[Serializable] public class Tree { string LeafColor; string Height; string LatinName; } }
Server: using System; using System.Runtime.Remoting; using RedGate.Common;
namespace RedGate.Server { public class Server { public void Main() { Environment.CurrentDirectory = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetEntryAssembly().Location);
RemotingConfiguration.Configure("RedGate.Server.exe.config", false); } }
public class Apple : IFruit { string GetName() { return "Apple"; }
string GetTree(Tree tree) { if (tree.LatinName.Equals("Malus domestica")) return "Apple Tree"; else return "No Idea"; } } }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.runtime.remoting> <customErrors mode="Off"/> <application> <service> <wellknown mode="SingleCall" type="RedGate.Server.Apple, RedGate.Server" objectUri="Apple.rem" /> </service> <channels> <channel ref="tcp" port="15200"> <serverProviders> <formatter ref="binary" typeFilterLevel="Full"/> </serverProviders> </channel> </channels> </application> </system.runtime.remoting> </configuration> Client:
using System; using System.Runtime.Remoting; using RedGate.Common;
namespace RedGate.Client { public class Client { public void Main() { RemotingConfiguration.Configure("RedGate.Client.exe.config", false); // This sadly won't work with an interface... // IFruit fruit = new IFruit(); IFruit fruit = (IFruit)Activator.GetObject(typeof(IFruit),
"tcp://richard:15200/Apple.rem"); Console.WriteLine(fruit.GetName()); } } } <?xml version="1.0" encoding="utf-8" ?> <configuration> <system.runtime.remoting> <application> <client> <wellknown type="RedGate.Common.IFruit, RedGate.Common" url="tcp://richard:15200/Apple.rem" /> </client> <channels> <channel ref="tcp" port="0"> <clientProviders> <formatter ref="binary"/> </clientProviders> <serverProviders> <formatter ref="binary" typeFilterLevel="Full"/> </serverProviders> </channel> </channels> </application> </system.runtime.remoting> </configuration>
There are a few key things to note here. If we use an interface we can't simply create the interface like we would any other object so the client config file becomes almost useless as we have to use the Activator.GetObject() call instead. Also I've set the typeFilterLevel property to Full or we wouldn't be able to pass our nice simple Tree class around instead we'd get a very scary looking SecurityException. Also notice that I have to set the Serializable attribute otherwise the .NET runtime wouldn't know how to throw my Tree class over the wire.
The config file for the client however isn't completely useless even though there's no way for me to use the <wellknown/> element. Bizarrely I've set a <serverProvider/> for the client. This will allow things like a Stream object to be passed over the wire and allow the call backs necessary to make it work although I don't make use of it in the example.
The config file in server is loaded from the directory of the location of the assembly. This is because in my implementation my server is a windows service. However the working directory of a windows service when run is c:\windows\system32 which means unless I change the working directory I can't load the config file. Another little gotcha that had me confused for a while.
All is good in remoting land until the client decides that Tree simply isn't enough and needs to subclass it to a Shrub (this little bit of information took me 4 hours to work out yesterday so listen closley). Well the interface still takes a Tree object so all should be well, however it won't be, because the marshaller sends over the details of the runtime type rather than the interface type so the server will attempt to deserialize a Shrub class which it doesn't know anything about. The work-around that seems to work at the moment is to implement ISerializable for the Tree class as follows... Shared:
using System.Runtime.Serialization;
namespace RedGate.Common { public interface IFruit { string GetName(); string GetFruitForTree(Tree tree); }
[Serializable] public class Tree : ISerializable { string LeafColor; string Height; string LatinName;
public void GetObjectData(SerializationInfo info, StreamingContext context) { // Setting this type forces the de-serialise to happen on the common type info.SetType(typeof(Tree));
info.AddValue("LeafColor", LeafColor); info.AddValue("Height", Height); info.AddValue("LatinName", LatinName); }
protected Tree(SerializationInfo info, StreamingContext context) { LeafColor = info.GetString("LeafColor"); Height = info.GetString("Height"); LatinName = info.GetString("LatinName"); } } } Client:
using System; using System.Runtime.Remoting; using RedGate.Common;
namespace RedGate.Client { public class Client { public void Main() { RemotingConfiguration.Configure("RedGate.Client.exe.config", false); // This sadly won't work with an interface... // IFruit fruit = new IFruit(); IFruit fruit = (IFruit)Activator.GetObject(typeof(IFruit),
"tcp://richard:15200/Apple.rem"); Console.WriteLine(fruit.GetName()); Shrub shrub = new Shrub(); shrub.Shape = "Round"; shrub.LeafColor = "Green"; shrub.Height = "4 feet"; shrub.LatinName = "Ribes oxyancanthoides"; Console.WriteLine(fruit.GetTree(shrub)); } }
public class Shrub : Tree { string Shape; } }
The important part here is of course is the call to SetType in the GetObjectData for the shared implementation of the Tree object. This ensures that the marshaller will try to instantiate an object of type Tree and not Shrub.
Hopefully this article has given you some ideas about .NET Remoting so that at least you won't make the same mistakes or get stuck at the same points that I have in the last few days.
Not sure if any of this code works as I've created the rather dubious example from hacking around code from the project that I'm working on. Still it'll give you the basic gist of how to go about these things.
|
-
Posted Thursday, January 24, 2008 11:22 AM |
It took a little longer than expected but "By George I Think We've Cracked It!". Towards the end of last year a bunch of us went out to go ice skating and otherwise spending the company's money - which was nice, earlier in the morning I managed to fall off my bicycle and then when I was showing somebody how to ice skate I fell over and cracked a rib. All this pain because we were out celebrating a whole bunch of cool projects that had come to an end during the year. Not content with merely cracking a rib I then contrived to make it even worse by contracting a cold so that I was in agony every time I coughed. This cold I then kindly passed on to loads of people at the Christmas party because I'm a sharing kind of guy (I tried to pass on the broken rib but they relieved me of the baseball bat at the door). This all goes to show you that developing software is painful, no really it is, can I hear sniggering at the back?
Yes, developing software is painful but sometimes it's even more painful when you realise your new baby isn't as perfect as you thought. This was the case with SQL Data Compare 6, we thought we'd cracked comparing to backups, we were happy and I was in physical pain - very much like having given birth in fact :D. Then a man came along with a problem, a fairly small database was taking hours to compare, we couldn't believe it, we routinely run 1000's of database compares every night, each showing up a specific set of circumstances. So after much scratching of heads we managed to get to the bottom of the issue and now the compare finishes in a few minutes - 4000% speed up anyone? Pretty much every database backup comparison will see an improvement in speed although not to that extent obviously.
Not only did we speed up SQL Data Compare when comparing to backups but we've also added a little sweetener, there is now an option to compress the temporary space used. This means that not only can you set the RGTEMP environment variable to move the temporary files but also they can be up to 80% smaller. OK we're compressing so it's going to take slightly longer but we're only seeing a 5 to 10% slow down in testing during the comparison. But actually the generation of SQL can be quicker as we're nowhere near as disk bound as we used to be, got big processors and big databases this is the feature you'll like most about SQL Data Compare 6.1.
What else did we do?
- Fixed some issues people were having with the synch wizard crashing
- Added a filter box for tables and views in the project configuration
- Try to not re-register backup files as the schema doesn't change that often does it :)
- WHERE clause failed if it ended with a comment --
- SQL Toolkit samples and help have been updated for version 6
- Healed 1 cracked rib
Hope you enjoy it out there, we're truly proud of what we've achieved.
Download SQL Data Compare here
|
-
Posted Monday, November 12, 2007 8:42 AM |
OK I admit it. During the development of SQL Data Compare 6 in order to get the product out on time we had to sacrifice doing the SQL Toolkit 6 help ( it didn't involve chickens). So I thought I'd write a little bit to get you started on the v6 stuff as it seems to be coming up. Those of you who've played with the latest version will appreciate how thoroughly cool comparing to a backup of a database is. So what we've done is given you that coolness in the latest version of the SQL Toolkit API. All you have to do is include a vast selection of dll references into your project and put a couple in the executable directory and you can make SQL Data Compare sit up and beg. Dll References
RedGate.BackupReader (Native backup files) RedGate.BackupReader.SqbReader (Red Gate SQL Backup files only) RedGate.Licensing.Client (has to be available for compile) RedGate.SQL.Shared RedGate.SQLCompare.ASTParser RedGate.SQLCompare.BackupReader (Backup SQL Compare engine) RedGate.SQLCompare.Engine RedGate.SQLCOmpare.Rewriter RedGate.SQLDataCompare.Engine (Your friend and mine)
Dlls with the executable
rglz.dll (for compressed Red Gate SQL Backup files) zlib1.dll (for compressed Red Gate SQL Backup files) RedGate.BackupReader.CryptoHelper.dll (for encrypted Red Gate SQL Backup files)
I know it looks like a scary amount of files to include in your project but really you can experiment and if you're not using Red Gate SQL Backup files you can ommit quite a few of the dependencies and is may still work - I've not really tested it. So we add all those lovely new files to our project. Make sure when you add them that they all come from the SQL Data Compare 6 directory only. This is because the version of the SQL Compare engine that shipped with SQL Compare 6 isn't the same as is shipped with SQL Data Compare. The code is actually remarkably simple to write once you've got the references set up. It goes something like this... // First register the backup file BackupDatabase backupDB = new BackupDatabase(); backupDB.RegisterForDataCompare(new string[] { "c:\\widgetdev.bak" }, null);
/* * Use this code to enumerate the backup sets in the file - you can pass one of * these objects in the call to RegisterForDataCompare() above *
IList<BackupSet> backupSets = backupDB.GetBackupSets( new string[] { "c:\\multiwidgetdev.bak" }); foreach (BackupSet backupSet in backupSets) { Console.WriteLine("{0} {1} {2} {3} {4}", backupSet.DatabaseName, backupSet.ServerName, backupSet.Size, backupSet.BackupType, backupSet.StartDate); } */
// Secondly register the live database Database liveDB = new Database(); liveDB.RegisterForDataCompare( new ConnectionProperties("localhost", "WidgetLive", "sa", ""));
// Create the mappings between the two schemas SchemaMappings mappings = new SchemaMappings(); mappings.CreateMappings(backupDB, liveDB);
// Compare the database ComparisonSession session = new ComparisonSession(); session.CompareDatabases(backupDB, liveDB, mappings); Job done. You can see all of the overrides for BackupDatabase.RegisterForDataCompare() which allow you to specify files, passwords, backup sets and data sources. The other main thing that we've added to the API is on the Project class. You've always been able to load a project via the API but not all the settings were applied, now however you have the lovely call you can make which is Project.ReplayUserActions(ref SchemaMappings). What this will do is set all the custom comparison keys, WHERE clauses and all the rest of the settings that make up the rest of the project not just which database you connect to. So you can set your project up using the UI and then run it via the API without issue. Mainly the rest of the API remains unaffected and there is really no issue in migrating your projects from v5 to v6. Hope this has given you a taste of what is available now, go forth and code most fruitfully.
|
-
Posted Wednesday, September 26, 2007 2:41 PM |
You've been waiting for it, we've been working on it and finally the day has arrived. SQL Data Compare 6 RC1 is available for download Right Now! Download RC1 here...We've very proud of what we've achieved with this release. You can compare to backups even better than you could in the Alpha. We've finished off all the features and we're just going through the final testing within Red Gate for the release but we thought we'd let you see it as it currently is. Briefly the main cool new features are...
- Compare to backups (SQL Backup or SQL Server) Pro version only
- Backup before synch (SQL Backup or SQL Server)
- 'Pivot' view
- Per-table synchronization SQL
- Differences navigation
- Improved textual difference view
- Reseed identity column
This version will sit alongside earlier versions of SQL Data Compare without a problem. If you installed the Alpha it is probably best if you uninstall it before installing the release candidate. There is the standard fully-functional 14-day trial for this product. Have fun with it and let us know of any issues on the SQL Data Compare Alpha Forum.Download RC1 here..
|
-
Posted Friday, September 21, 2007 1:13 PM |
|
Just to let you know that we're contacting the people who've helped out with the SQL Data Compare 6 Alpha and are in the process of getting your likkle iPods to you as I speak.
Thanks to everybody who helped out, the release is looking really good now, we're just doing a few last bug fixes then it's ready for install testing. I hope to put a release candidate up for the really keen to try out next week the final release being early October.
Also I've noticed that I've lately become addicted to anonymous delegates. Do you think there is somewhere I can get therapy? I find myself writing looping code which takes a delegate for the conditional statement as its argument. I even find myself writing whole threads as anonymous delegates.
Help...I think it's finally got to me...!!!!
new Thread(delegate { DoStuffInBackground; if (IsHandleCreated) Invoke(delegate { DoFinishingStuffOnUiThread; }); }).Start();
|
-
Posted Thursday, September 13, 2007 8:27 AM |
|
Until recently I wouldn't have said much. I'm talking about software release names rather than personal names - I quite like my name, it was the name my Grandad on my dads side who died when my dad was still quite young. But apart from that, I'm talking about the terms that seems to be bandied around almost interchangeably recently.
Words like Alpha and Beta have been the fodder of software releases for a good long while, then new acronyms started to appear like mushrooms in a school football field (another childhood memory). Things like RC - sounds good then you get RC1 RC2 RC3 .. RCn which when you start getting n > 3 you don't know what you're doing. Now we get Microsoft in on the act with CTP which sounds all cuddly and you're really really part of our community, isn't it nice that we're friends now. They don't even bother to use n just date it so they can produce as many as they like and nobody gets any the wiser.
In the open source world you get things like Stable, Development and Nightlies (I always think of my Grandma with that word - take out the l) fair enough you know more or less what you're getting. If you want stability you, shock horror, choose the stable build. Only if you're truly bleeding edge do you go for the nightly.
Now back to this - what's in a name. We release SQL Data Compare 6 Alpha lately and it seemed to go down very well, so well in fact that we cancelled the Beta program entirely and are now going all out for release sometime early in October. But I made a mistake in the first place - I called it an Alpha. This brings connotations of the Alphas of old which could quite happily trash your machine and leave you having the re-install. My meaning was just to try to signify that the product wasn't feature complete. However we didn't get quite the usage out of the Alpha that we'd have hoped for. Basically, should have called it a Beta.
We've not forgotten about the iPod shuffles for all those people who tried out the Alpha and I'll be trying to organise that after the code freeze which should happen this week (will luck).
|
-
Posted Wednesday, August 01, 2007 9:22 AM |
Fresh off the presses and with the ink still drying we've pushed SQL Data Compare 6 Alpha out of the door. There are full release notes available here which tells you how to download it and the issues we know about. The product is supported only via the forums which can be found here. Some of the cool stuff for you to play with is. - Compare to backups, be they full or differential, SQL Server or SQL Backup.
- 'pivot' view - our new visualisation for table differences
- Projects are more file based
Hope you enjoy it and please post your experiences good or bad on the forum as there's still time to fix things before the release :).
|
-
Posted Thursday, July 26, 2007 9:52 AM |
After over 3 months of hard graft we're getting ready to give you the chance to get your fingers on the Alpha of the next version of SQL Data Compare. We're currently just doing some final install testing and hope to release it next week. Bear in mind the product is an Alpha and as such it isn't actually complete yet, some of the features that didn't make it yet are... - Backup before synch
- UI for project actions warnings
- UI to allow you to select backup files from multiple directories
However we're really keen on getting people playing with the new features as early as possible. The main reason for the Alpha is to get your feedback on the compare to Backup feature that has been the main focus of our work to date. This will allow you to use data compare to compare to a SQL Server Backup file or Red Gate SQL Backup file (sqb) as if it was a live database. We would love for you to try it out on your backups, we've tested it against several hundred databases that we have in house but there'll always be something missing so the earlier we get feedback the more time we have to fix it prior to release. Some of the other things we would like people looking at and giving opinions on is the improved usability features of the UI. For example projects are no-longer saved automagically when you don't expect it, behaving instead much more like a standard windows project system so you can save your changes (or not) whenever you see fit. Also the 'pivot' view that I've previously blogged about is something we're keen for feedback on. We'll be following the Alpha with a feature complete Beta in roughly a month and your feedback from the Alpha will be key in making it work how you need it to. So next week - watch this space....
|
-
Posted Thursday, July 12, 2007 9:55 AM |
I'm sure you all make changes to your schema over time adding columns to tables and occassionally dropping them. But were you aware that even though you drop a column from a table the space in the row continues to be taken up by the ghost of the column that you deleted. So if you make lots of schema changes to a database over time the row becomes much larger than it needs to be.
Of course this has the interesting effect that in the syscolumns table the colid for your rows aren't sequential so they can't be used as an index.
Just a little thing to be aware of and one of those things that doesn't seem to be mentioned in books on-line ( at least in the 5 minutes I spent looking for it this morning ).
CREATE TABLE ItsTooBig (col1 CHAR(100), col2 CHAR(100))
SELECT name, colid, xoffset
FROM syscolumns
WHERE OBJECT_ID('ItsTooBig') = id
DECLARE @i INT
SET @i = 1
WHILE @i < 100
BEGIN
INSERT INTO ItsTooBig
VALUES (1,@i)
DECLARE @command VARCHAR(50)
SET @command =
'alter table ItsTooBig drop column col'
+ CAST(@i AS VARCHAR(3))
EXEC(@command)
SET @i = @i + 1
SET @command =
'alter table ItsTooBig add col'
+ CAST((@i+1) AS VARCHAR(3))
+ ' char(100)'
EXEC(@command)
IF @i % 10 = 0
SELECT @i, name, colid, xoffset
FROM syscolumns
WHERE OBJECT_ID('ItsTooBig') = id
END
DROP TABLE ItsTooBig
Take care out there people - those columns are out to get you.
|
-
Posted Monday, July 09, 2007 7:54 AM |
In my history as a programmer there are a few occasions that stand out when I feel I've written something truly special (yes there's a Red Gate bit but that comes later). The difficulty I generally find is how to quantify special. Mainly I think of this of the user being able to use the thing produced for something that it was originally not designed to do, or some feature that is obvious that users enjoy and make use of. Now I admit, I'm not a back-office programmer, there's nothing I like less than to write a program that nobody ever sees and just sits there doing it's job quietly and efficiently without anybody realising it exists. I like to create tools for users, I like to create tools for fellow programmers and these are my 'users'. So something special. Here are a few examples that I consider special. Now I know initially this doesn't sounds very interesting but really the only way this conforms to my definition of special is that users loved the feature. All I had to do was create a background for the testing suite and for reasons I'll not go into it had to take up the whole screen and appear as non-computery as possible. So I created a user control the drew a gradient from one colo(u)r to another. Simple, then I chose some colo(u)rs. But because I was feeling generous and I desperately wanted to re-use my user control I placed it on the options screen allowing people to choose the colo(u)rs and lo and behold every-single-different user I ever saw had different colo(u)rs on their background. It was a simple feature but one that made users very happy and for that reason it was special.
- Making everything an option
For the same company I also produced an automated system that was computer controlled. However it was trying to re-create something that was inherently a user only operation and because of the external influences on the conditions of what the program was operating on the operating parameters changed regularly. So I created an options screen that was based on an internal XML data structure meaning I could add parameters simply by changing the XML and they would be available to the UI and me coding the program. The number of options was staggering for such a small program - I think it got up to several hundred arranged in a tree-structure. However the operators loved it and some of the settings that they created to use the program baffled me as I'd never thought of setting the options in to me a non-sensicle manner. But it worked and they thought it was special.
The next bit of work I performed that I consider special was when I created a querying system for a company that created dynamic websites. The problem was that each page was a list of articles be they jobs/news/events/etc. Previously this was done by up to 200 stored procedure calls per page displayed, obviously this wasn't scaling well so I was brought in to fix the problem. What I created was a bit of a beast, it was an 800 line stored procedure that did everything including manufacture the kitchen sink. However on top of this I was able to introduce three levels of caching. The last level was a HTML cache, it turned out to be a 30 minute job and when it went live all the websites sped up by about 500% on cached pages. The webmasters and users of the sites loved it of course. The system wasn't really designed to have this extra cache but the design was special so it's implementation was really easy and effective.
- Mapping! Who'll use mapping?
OK I know this is a Red Gate bit but bear with me. When we SQL Data Compare 5 we introduced a feature called mapping, this allowed users to compare a table in one database with a table in another database regardless of the name or even the columns as you could map from one to the other. This has proven quite popular although the special feeling came when I heard about a user who had used mapping to compare a table in one database to itself! He managed this by creating a mapping one the table to itself and then set the WHERE clause to set the rows to be compared from one side to the other. I was amazed that it could work and the user using that feature for something other than it was intended made me think that the feature was special.
There are other things that I've done over the years, most recently our comparing to backups API was designed from the start as a bolt-on component of SQL Data Compare and the integration has only taken half of the time estimated because we got it right - that's special. What do you think makes a creation special? Can you think of things you've done that your users love or that is used in a creative way that you didn't intend. *phew anybody got some plasters, my fingers are bleeding after all that typing*
|
-
Posted Friday, June 22, 2007 12:38 PM |
Don't you just love them. You write your UI, you think you design you code you fix you bug fix again when testers break everything in sight you perform usability trials on people and they don't even find that feature you worked on for 2 weeks. Well ok it's not quite that bad and this is one of the reasons why we're so keen on running usability trials for Red Gate tools that we produce. We've just started the usability trials for the upcoming SQL Data Compare 6 Alpha and it looks like there's going to be a bit of work to address some of these problems. For example, one of the new features I'm really keen on is the ability to 'pivot' a table view. So instead of your fields going across the top and your rows going down, your fields now go down and your rows go across. This means that you can see whole row data for tables that have a fair number of fields, really only limited by the height of your monitor. The difficultly we're getting is what row should people be on when they 'pivot' the view? Initially we thought - hey we'll make the row that was at the top be the row that is on the left - that'll work nicely. Nope, people seem to lose track of where they were. OK, so we'll put them on the current selection - but we can't do that as the selection may be multiple rows so where should I go? All very interesting and hopefully we'll come up with something that you will like. Still at least we've got an Alpha and I like opinionated people testing our stuff, please be opinionated. So as for a little taster here's a screenshot of the new layout - what do you think?
|
-
Posted Monday, June 18, 2007 8:44 AM |
In between the bouts of champagne for new product launches, eating the yoghurts and drinking the smoothies from the 'feel good fridge'. In between the free Thursday lunches and punting on the Cam we manage to get a surprising amount of work done here at Red Gate. In fact I've been radio silent for the past couple of months mainly as we've been slogging away at the upcoming new version of SQL Data Compare 6. Now if you thought SQL Data Compare 5 was a step forward with it's amazing schema/table and column level mapping support ( I like that feature as I wrote it :) ), you'll be astounded as to what we've got for you in version 6. OK we made a few mistakes in version 5. The project don't behave quite as you'd expect them to, the mappings you patiently created tend to disappear without warning and the very subtle (too subtle) colouring of the difference viewer makes it hard to spot differences in your table. Well you'll be pleased to hear we've fixed all that, projects are once again explicitly saved, you don't lose your mappings and OK the colours may be garish but at least you can find the differences in your objects. Well we've got all that and more but what have we got that's truly new? You ready? Can you stand the suspense any longer? Is this like one of those annoying emails that tell you to send it to all your friends or you'll get piles? I hope not. You will be able to compare to backups in version 6, without having to restore the backup file or even copy it to a local disk. You can of course even restore from a backup the contents of a table or even just an individual field much faster than copying the file from the network location to a SQL Server, restoring the database and the comparing the data. It'll even work on SQL Backup 5 compressed and encrypted backups. I mean how seriously cool is that? We've loved working on this new feature and we're getting close to letting all you out there have a play with it. One of the reasons behind getting an early Alpha out of the door is that we really really want your input in to how it works and of course how it doesn't work. That's the whole point of Alphas really, we know there'll be bugs but we'd love your help in making this the best SQL Data Compare release ever. If you can't tell by now I'm a little excited at the possibilities of this new version, it creates a whole new use for SQL Data Compare that we really couldn't have imagined before. If you want to get involved in the Alpha and subsequent Beta releases drop me an e-mail and I'll get back to you when the Alpha is released. I love working on SQL Data Compare, the engine is a thing of beauty and the UI is pretty nice to work with too. This new feature brings together many technologies that we've become experienced in from SQL Compare, SQL Log Rescue (which is now free) and of course SQL Backup. Hope you like it.
|
-
Posted Thursday, May 17, 2007 9:48 AM |
One thing that has annoyed me quite a lot lately is the way that cut-n-paste code from visual studio 2005 fails to look nice in emails. Your tabs dissappear you very large line gaps for every new line in your code and it sets the text to be a very strange font. Now maybe it's just me and my usage of the ancient Outlook 2003 but this has always bugged me. I do tend to send code snippits to quite a few people via email to clear up problems with programming for ANTS Profiler and SQL Toolkit (look ma' links). After prompting from Rob who works beside me you can fix this annoyance by pasting your code into Word and then cut and pasting from word into your email ( assuming your email is in HTML format ). Voila! Robert's your fathers brother. Bingo! Yahtzee! The code looks just like it did in visual studio. Now if only I could be bothered to write a macro or add-in which did it straight from Visual Studio it would be wonderful.
|
|
|