Dealing with conflict in SVN

Okay, you have finished working on a cool new feature in your app. It works perfectly on your machine, and you can’t wait to let the world know about it. But first, you should commit your work to the central SVN server so the other team member could see it.

Commit

image

In SVN, you do a commit operation to send your local changes to the central repository. Generally, my rule for commit is to do it as often as I could. Of course, to avoid upsetting the other team member, I must also ensure that the code I commit is compilable.

Why I have to do it frequently, you ask? The rule of thumb is, whoever commit first, wins. If someone happens to commit before you do, instead of the usual success message, you may ends up with something like this :

image

Update

image

Ok, because we ‘lose’ in the commit ‘race’, we have to do an update. Just right-click, update. How bad could that be?

You do an update to get the latest version from the central repository, and merge them with your local changes. The result could be one of the following :

no remote changes

remote changes exist
no local changes

unchanged

updated
local changes exist modified merged / conflicted

If you have updated a file, and the server also has changes on the same file, you may be experiencing something called *drum roll please* conflict.

Conflict

Conflict is the worst thing could happen after an update. It means your local and the server both have changes, and the SVN doesn’t know how to deal with it (if it does, it will be automatically merged).

A conflict basically means SVN asks for your help to merge the changes. In order to assist you resolving the conflict, SVN has kindly insert a conflict marker on the conflicted files. Well, the intention is good, but as the saying goes, the road to hell is paved with good intentions.

In my earlier time working with SVN, I realized that there is an option labeled resolved. I happily click it, and the conflict suddenly gone. The file is now marked as modified, and ready to be included in a commit.

That’s it? Well, if you really look at the content of the file, you’ll realize that it is quite a mess. Your local changes is still there, so are the remote changes from the server, plus the conflict marker inserted by SVN is also there. That is definitely not what I want.

image

The correct way to handle the conflict is by using the Edit conflicts menu. You’ll see three panes, one for the remote changes (theirs), one for your local changes (mine), and the large one is for the merged version.

image

Also, on the indicator in the left, look for a red sign. That’s where the conflict is.

You have the option to discard one version, and keep the other, or keep them both in a particular order. Basically, you are in control now.

image

Once you are happy with the merged version, you can safely mark the file as resolved (image ). Now you can confidently commit your changes.

PS : For a more comprehensive guide on SVN conflict, you can go here.

Advertisement

Working with Oracle in .NET – part IV : CRUD

So far, this is what we have done :

  1. Creating a schema in SQL Server, identical with our Oracle schema using SSMA.
  2. Generate the DAL using T4 template and the identical schema in SQL Server.
  3. Provide a parameter-less constructor to simplify the usage of the DAL.

Now it is time to actually using the DAL to work with our Oracle database. For examples in this article to work, you will need to include the BLToolkit.Data.Linq namespace in your using clause.

using BLToolkit.Data.Linq;

Insert

Use the following method if your table have an auto-increment column as its primary key, and you want to retrieve the newly inserted identity :

MyTable newData = /* get your new data somewhere */;
var newId = Convert.ToDecimal(db.InsertWithIdentity<MyTable>(newData));

Change the conversion part to match the type of your identity column.

Please note though, the above method generates an SQL statement that sets the value of the primary key column too (while actually we want the RDBMS to generate the value for us). Depends on your database design, this may lead to an undesirable result.

For my case, the above method works fine because in my database, the primary key will always auto-generated by Oracle, effectively discarded the value provided by the user (it explained here). If you don’t have an equivalent setup in your database, you better use the following alternative :

var newId = Convert.ToDecimal(db.MyTable.InsertWithIdentity(() => new MyTable { 
    /* populate all the column here, excluding the identity column */
    Description = "new item",
    Price = 2000
}));

The disadvantage of the above approach is you must populate the new object once again inside the object initializer, skipping the identity column. I’ve seen someone complaining about this, and apparently it can be avoided by decorating the identity column with NonUpdatable attribute. However, I haven’t tried that approach yet.

Bulk Insert

If you need to insert multiple items at once, use the InsertBatch method :

List<MyTable> newItems = /* get your new items somewhere */;
db.InsertBatch<MyTable>(newItems);

Update and Delete

Previously, I’ve been using Linq to Sql (L2S) as my ORM. In L2S, as far as I know, you need to select the data before you can update or delete them. The similar pattern is possible using BLToolkit :

/* single item */
MyTable data = /* get your data somewhere */;
db.Update<MyTable>(data);
db.Delete<MyTable>(data);

/* multiple items */
List<MyTable> list = /* get your data somewhere */;
db.Update<MyTable>(list);
db.Delete<MyTable>(list);

However, for some cases, this pattern is far from efficient (you can read more about it here or here). Fortunately, BLToolkit has provided update / delete operation using predicate, effectively providing us with an efficient bulk operations :

/* update the status of all expired items */
db.MyTable.Update(p => p.ExpiredDate.Date < DateTime.Now.Date, p => new MyTable { Status = "Expired" });/* delete all expired items */
db.MyTable.Delete(p => p.Status == "Expired");

Select

IMHO, BLToolkit have an excellent LINQ support. Standard every day operations like filtering, sorting, and paging is quite straightforward :

/* fluent style */
var data1 = db.MyTable.Where(p => p.Description.Contains("keyword")).OrderBy(p => p.Description).Skip(10).Take(10);                /* query style */
var data2 = (from p in db.MyTable where p.Description.Contains("keyword") orderby p.Description select p).Skip(10).Take(10);

BLToolkit also has association feature that provide a neat alternative to LINQ’s join. You can read more about it here. Of course, if you really need to, you can also doing the join operation using LINQ too. For more information of other possibilities, you can read here or here.

You can also use other library for LINQ like LinqKit and their PredicateBuilder for more filtering options, or Dynamite to provide a dynamic sorting capabilities.

Custom Query

Apart from generating the SQL for us, BLToolkit also allowed us to execute a custom query. I personally use this feature when I was working with Sphinx.

using (var db = new SphinxDbManager())
{
    var query = string.Format(
        "select catalogid from catalog where match('@value \"{0}\" @tag 245 @subruas a') group by catalogid limit 0, 1000000 option max_matches = 1000000",
        title.EscapeSphinxSpecialChar());
    return db.SetCommand(query).ExecuteList<CatalogDocument>().Select(q => q.CatalogID).ToList();
}

Stored Procedure

Frankly speaking, I don’t use the keep-it-in-stored-procedure development style. But from what this article says, it seems good enough. If you need stored procedure support, maybe you can use the article as a starting point, besides the BLToolkit documentation itself.

Debugging the SQL

Ever wondered what kind of SQL produced by BLToolkit? The DbManager class has a property called LastQuery. This property contains the last query sent to the database server. As an Oracle newbie, I learned a lot of PL/SQL from this property 🙂

The SQL in DbManager’s LastQuery is still in a parameterized form. If you want to know the value of the parameters, you should store the IQueryable in a variable. The IQueryable has a SqlText property, where you can see the value assigned to the parameters (in a commented form), beside the query itself. This way, you can get a deeper insight of what happened under the hood.

image.png

Working with Oracle in .NET – part III : DbManager

After successfully compiled our generated DAL, now it is time to use the DAL to actually access our Oracle database from our .NET applications.

Add reference to BLToolkit Oracle data provider

image

Modify your configuration file

This is what mine looks like :

<configuration>
  <configSections>
    <section name="bltoolkit" type="BLToolkit.Configuration.BLToolkitSection,   BLToolkit.4" />
  </configSections>
  <bltoolkit>
    <dataProviders>
      <add type="BLToolkit.Data.DataProvider.OdpDataProvider,     BLToolkit.Data.DataProvider.Oracle.4" />
    </dataProviders>
  </bltoolkit>
  <connectionStrings>
    <add name="MyConnectionString" connectionString="Data Source=localhost/xe;User ID=user;Password=password;" providerName="Oracle.DataAccess.Client" />
  </connectionStrings><!-- other entries
...
...
...
-->

Tips : you can easily accomplish both step by simply installing the library from NuGet.

bltoolkitoraclenuget72

Usage example

A typical usage of the DAL would be something like this :

using (var db = new MyDbManager("MyConnectionString"))
            {
                db.BeginTransaction();
                try
                {
                    /*
                     * do something with the database
                     */
                    db.CommitTransaction();
                }
                catch 
                {
                    db.RollbackTransaction();
                    throw;
                }
            }

Simplifying the usage

Do you notice the parameter supplied to the DbManager’s constructor? It is the name of the connection string we’ve added to the web.config in the earlier step. It has to be done every time we instantiate the DbManager, which is very often in my case. To me, magic string like this is not a good thing.

To avoid supplying an arbitrary string like this every time we need to access the database, we can add a parameterless constructor to the DbManager. But since this class is auto-generated, modifying the class directly is not a good option. Instead, as the DbManager is declared as partial, we can add another partial class to achieve this. This is what my class looks like :

public partial class MyDbManager : DbManager
    {
        public MyDbManager()
            : base("MyConnectionString")
        {
        }
    }

Ensure you specify this class in the same namespace with the generated DAL.

With this addition, we can now create the DAL without supplying any parameter.

using (var db = new MyDbManager())
            {
                db.BeginTransaction();
                try
                {
                    /*
                     * do something with the database
                     */
                    db.CommitTransaction();
                }
                catch 
                {
                    db.RollbackTransaction();
                    throw;
                }
            }

Another advantage of this approach is, if the connection string name needs to be changed in the future, we only need to modify a single string in our code. Handy, isn’t it?

On the next article I will cover about doing basic CRUD operation against our Oracle database.