App config:

<domains>
    <domain name="Default" upgradeMode="Recreate" connectionUrl="sqlserver://localhost/DO40-Tests" >
                <types>
                    <add assembly="BugProject" />
                </types>
            </domain>
            <domain name="DefaultSome" upgradeMode="PerformSafely" connectionUrl="sqlserver://localhost/DO40-Tests" >
                <types>
                    <add assembly="BugProject" />
                </types>
            </domain>
            <domain name="DefaultSome2" upgradeMode="Validate" connectionUrl="sqlserver://localhost/DO40-Tests" >
                <types>
                    <add assembly="BugProject" />
                </types>
            </domain>
        </domains>

model1 (case1):

namespace BugProject.Model
{
    using System;
    using Xtensive.Orm;

    [Serializable]
    [HierarchyRoot]
    public class MyEntity : Entity
    {
        [Field, Key]
        public int Id { get; private set; }

        [Field]
        public MyEntity SomeField { get; set; }

        public MyEntity(Session session) : base (session)
        {
        }
    }

    [Serializable]
    [HierarchyRoot]
    public class MySecondEntity : Entity
    {
        [Field, Key]
        public int Id { get; private set; }

        public MySecondEntity(Session session) : base(session)
        {
        }
    }
}

project (case1):

namespace BugProject
{
using System;
using Xtensive.Orm;
using Xtensive.Orm.Configuration;
using BugProject.Model;

class Program
{
    public static void Main(string[] args)
    {
        var configRecreate = DomainConfiguration.Load("Default");
        var configPerformSafely = DomainConfiguration.Load("DefaultSome");
        var configValidate = DomainConfiguration.Load("DefaultSome");
        Domain domain = null;
        try
        {
            domain = Domain.Build(configValidate);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            Console.WriteLine();

            try
            {
                domain = Domain.Build(configPerformSafely);
            }
            catch (Exception k)
            {
                /*
                * Base do not exist or:
               * sql server error. That's mean that change field type is safily???? 
               * If change field type from value type to referenced, 
               * this shown in unsafe actions(ok, that's good)
               */
                Console.WriteLine(k.ToString());
                Console.WriteLine();
                domain = Domain.Build(configRecreate);
            }
        }

        if (domain == null)
        {
            Console.WriteLine("Error!");
            return;
        }

        using (var session = domain.OpenSession())
        {
            using (var transactionScope = session.OpenTransaction())
            {
                var some1 = new MyEntity(session);
                var sometest1 = new MySecondEntity(session);
                var some2 = new MyEntity(session)
                                {
                                    SomeField = some1                                        
                                };
                transactionScope.Complete();
            }
        }

        Console.WriteLine("Close program. Press any key.");
        Console.ReadKey();
    }
}

}

Then do some changes and have exceptions:

model1 (case2):

namespace BugProject.Model
{
    using System;
    using Xtensive.Orm;

    [Serializable]
    [HierarchyRoot]
    public class MyEntity : Entity
    {
        [Field, Key]
        public int Id { get; private set; }

        [Field]
        public MySecondEntity SomeField { get; set; }

        public MyEntity(Session session) : base (session)
        {
        }
    }

    [Serializable]
    [HierarchyRoot]
    public class MySecondEntity : Entity
    {
        [Field, Key]
        public int Id { get; private set; }

        public MySecondEntity(Session session) : base(session)
        {
        }
    }
}

project (case2):

namespace BugProject
{
using System;
using Xtensive.Orm;
using Xtensive.Orm.Configuration;
using BugProject.Model;

class Program
{
    public static void Main(string[] args)
    {
        var configRecreate = DomainConfiguration.Load("Default");
        var configPerformSafely = DomainConfiguration.Load("DefaultSome");
        var configValidate = DomainConfiguration.Load("DefaultSome");
        Domain domain = null;
        try
        {
            domain = Domain.Build(configValidate);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
            Console.WriteLine();

            try
            {
                domain = Domain.Build(configPerformSafely);
            }
            catch (Exception k)
            {
                Console.WriteLine(k.ToString());
                Console.WriteLine();
                domain = Domain.Build(configRecreate);
            }
        }

        if (domain == null)
        {
            Console.WriteLine("Error!");
            return;
        }

        using (var session = domain.OpenSession())
        {
            using (var transactionScope = session.OpenTransaction())
            {
                var some1 = new MyEntity(session);
                var sometest1 = new MySecondEntity(session);
                var some2 = new MyEntity(session)
                                {
                                    SomeField = sometest1
                                };
                transactionScope.Complete();
            }
        }

        Console.WriteLine("Close program. Press any key.");
        Console.ReadKey();
    }
}

}

After first run with case1 created base, errors meaningless now, then change in some entity field type from some referensed type to another.

Run with case2 Validare crashed(ok, that's good), BUT(!!!!!) in SchemaSynchronizationException we don't see any unsafe actions. And if try run on PerformSafily we have error from sql server

Don't write any hints.

I rigth understand, that change field type from one referenced to another it's a safe action??

Example:

var nodeDifference = (SchemaSynchronizationException.ComparisonResult.Difference as NodeDifference);
var propertyChange = nodeDifference.PropertyChanges
                .Where(a => a.Value as NodeCollectionDifference != null)
                .Select(a => a.Value as NodeCollectionDifference)
                .FirstOrDefault();
foreach (var changedEntity in propertyChange.ItemChanges.Where(a => (a.IsChanged || a.HasChanges) && a.MovementInfo != MovementInfo.Removed && a.MovementInfo != MovementInfo.Created))
{    
    var entityName = changedEntity.Source.Name;
    var changesProperty = changedEntity.PropertyChanges.ToArray();
    var valuePairs = changesProperty.Where(a => a.Value as NodeCollectionDifference != null && a.Key == "Columns");        
 }

valuePairs is empty, that mean we don't have changes in base struct... Only foreign keys changing.

I apologize for the errors in the text

asked Nov 10 '11 at 02:13

Multysh's gravatar image

Multysh
15669

edited Dec 20 '11 at 05:34


One Answer:

Hello Multysh,

The comparison is executed against 2 database schemes, therefore on that level there is no differences between SomeEntity.Id INT column from the extracted scheme and SomeEntity.Id INT column from the freshly built one. The structure of tables and columns doesn't change, so unsafe actions are not found.

As for the case when you change field type from reference type to int type you actually change the name of the column from SomeEntity.Id to Id or something else, as a result, without defining a corresponding rename hint you get an unsafe action for removing SomeEntity.Id column.

Hope that helps in better understanding of upgrade specifics.

answered Nov 10 '11 at 08:49

Dmitri%20Maximov's gravatar image

Dmitri Maximov
22111211

A minor note:

as this website is an international support service, please, try using English. Thanks.

(Nov 10 '11 at 08:52) Dmitri Maximov Dmitri%20Maximov's gravatar image

I understand why this is so, but still do not quite agree that it's not a bug :)

(Nov 10 '11 at 09:05) Multysh Multysh's gravatar image

I'm trying to automate the writing hints and analyze drops of keys is difficult. It is difficult to analyze ChangeFieldTypeHint

(Nov 10 '11 at 09:09) Multysh Multysh's gravatar image

Yeah, I agree, this might be disputable.

(Nov 10 '11 at 09:12) Dmitri Maximov Dmitri%20Maximov's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA