четверг, 5 сентября 2013 г.

Как подключиться к Teradata из MS Visual Studio

Я убил много времени на этот пустяк, с Oracle все получилось без проблем.
Я опишу два способа:
1) Через ODBC.
Скачиваем Teradata Client, устанавливаем и настраиваем наш ODBC источник (системный).
Проверить можно через Teradata SQL Assistant.
В нашем проекте добавляем

 
using System.Data.Odbc;


и добавляем:

 
string queryString = "insert into  TABLE values(1,1,1,1,1,1,'2013-09-04')";



            OdbcCommand command = new OdbcCommand(queryString);



            using (OdbcConnection connection = new OdbcConnection("Dsn=ODBCname;uid=user_id;Pwd=password;"))

            {

                command.Connection = connection;

                connection.Open();

                command.ExecuteNonQuery();

 
}
2) Через Teradata.Client.Provider
Добавляем в References данную сборку из клиента Teradata.
 using Teradata.Client.Provider;

Далее:
  
                TdConnectionStringBuilder conBuilder = new TdConnectionStringBuilder();
                conBuilder.DataSource = "host";
                conBuilder.Password = "pass";
                conBuilder.UserId = "user";
                
                conBuilder.Database = "DBName";
                conBuilder.SessionMode = "TERADATA";
                conBuilder.AuthenticationMechanism = "SPNEGO";
                conBuilder.SessionCharacterSet = "UTF8";
                TdConnection connection = new TdConnection();
                connection.ConnectionString = conBuilder.ConnectionString;
                connection.Open();
SPNEGO должен быть включен в Teradat-е, по умолчанию он выключен.

воскресенье, 1 сентября 2013 г.

Паттерн стратегия

Здесь я хотел бы рассказать о паттерне стратегии.

В качестве примера, рассмотрим следующий класс:
    abstract class Duck
    {
        public void quack()
        {
            Console.Out.WriteLine("Quack!");
        }

        public void swim()
        {
            Console.Out.WriteLine("Bulk!");
        }

        abstract public void display();
    }

     Это наш класс Утка, которая умеет крякать и плавать, при этом все утки, которые наследуют этот класс умеют тоже самое. Метод display у нас является абстрактным, так как каждая утка имеет свой образ и требует конкретной реализации.
Ниже я показал диаграмму классов (у нас две новых утки: MallarDuck и RedHeadDuck, которые наследуют абстрактный класс Duck):



Класс MallarDuck:

using System;

    class MallarDuck : Duck
    {
        public override void display()
        {
            Console.Out.WriteLine("I am Mallar Duck!");
        }
    }

Класс RedHeadDuck:

using System;
   class RedHeadDuck : Duck
    {
        public override void display()
        {
            Console.Out.WriteLine("I am Red Head Duck!");
        }
    }
Запускаем наш первый пример:
using System;

    class Program
    {
        static void Main(string[] args)
        {
            MallarDuck  MyDuckMallar = new MallarDuck();
            RedHeadDuck MyDuckRedHead = new RedHeadDuck();
            
            MyDuckMallar.display();
            MyDuckRedHead.display();
            
            MyDuckMallar.quack();
            MyDuckRedHead.quack();

            Console.In.ReadLine();

        }
    }

Результатом запуска будет:

Какие проблемы сразу видны?
    Если мы заходим дать возможность нашим уткам летать, то необходимо будет добавить в наш абстрактный класс Duck метод fly(), при этом его конкретную реализацию унаследуют все классы, т.е. даже те утки, которые не должны летать. Для них нам придется переписывать данный метод и делать его пустым (например деревянная утка не должна уметь летать). При добавлении других возможностей в будущем, каждый  раз придется реализовывать пустые методы.

Какой Выход?
    Возможно, стоит вынести метод fly() в интерфейс? Тогда мы достигним того, что деревянная утка не должна летать, так как она не будет реализовывать интерфейс метода fly().
Но тут возникает другая проблема: дублирование кода. Так как интерфейс не может содержать конкретную реализацию метода, то нам придется реализовывать метод fly() для каждого класса. При каких-либо изменениях, необходимо будет внести их в каждый класс.

Основным принципом проектирования является: Выделить части приложения, которые могут изменяться и отделить их от тех, которые являются постоянными. Иными словами нам нужно выделить изменяющийся код так, чтобы не изменять постоянную часть в дальнейшем.

Принцип проектирования: Программируйте на уровне интерфейсов.

Руководствуясь этими двумя принципами переделаем наш пример.
 Мы знаем, что метод fly() может быть не у всех субклассов класса Duck, поэтому нам необходимо выделить его в отдельный набор классов, так же как и метод кряканья quack().
Руководствуясь первый принципом мы должны создать интерфейс для методы fly()

Получаем следующую диаграмму классов:


Давайте посмотрим на изменившийся класс Duck:


    abstract class Duck
    {
        //переменные интерфейсов, 
        //через которые будет происходит делегирование действий
        protected IFlyBehavior flyBehavior;
        protected IQuackBehavior quackBehavior;

        //создаем динамическое изменение поведения уток
        public void setFlyBehavior(IFlyBehavior fb)
        {
            flyBehavior = fb;
        }

        public void setQuackBehavior(IQuackBehavior qb)
        {
            quackBehavior = qb;
        }

        public void performQuack()
        {
            quackBehavior.quak(); //делегируем
        }

        public void performFly()
        {
            flyBehavior.fly(); //делегируем
        }

        public void swim()
        {
            Console.Out.WriteLine("Bulk!");
        }

        abstract public void display();
    }

Мы вынесли методы полета и кряканья в интерфейсы, а также сделали набор классов, которые являются реализацией разных алгоритмов полета и кряканья наших уток. Далее мы объявили две переменных в абстрактном классе Duck()
  protected IFlyBehavior flyBehavior;
  protected IQuackBehavior quackBehavior;
Которые ссылаются на классы, реализующие данные методы. Т.е. мы можем присвоить любой алгоритм кряканья или полета. Вызов делегирование происходит через методы:
        public void performQuack()
        {
            quackBehavior.quak(); //делегируем
        }

        public void performFly()
        {
            flyBehavior.fly(); //делегируем
        }
С помощью двух сеттеров мы можем динамически на лету присваивать разные алгоритмы нашим классам. Метод display() мы оставили абстрактным, так как для каждой утки он будет разным, а метод swim() для всех будет одинаков. Ниже приведу описание остальных классов:
    //интерфейс метода Полета
    interface IFlyBehavior
    {
        void fly();
    }
   // интерфейс метода кряканья
    interface IQuackBehavior
    {
        void quak();
    }
  //класс, реализующий невозможность летать
  class FlyNoWay: IFlyBehavior
    {
        public void fly()
        {
            Console.Out.WriteLine("I can not fly!");
        }
    }
  //Класс, реализующий алгоритм полета ракеты
  class FlyRocket: IFlyBehavior
    {
        public void fly()
        {
            Console.Out.WriteLine("I fly as rocket!");
        }
    }
  //Класс, реализующий алгоритм обычного кряканья
  class Quack : IQuackBehavior
    {
        public void quak()
        {
            Console.Out.WriteLine("quack!");
        }
    }
  //Класс, реализующий алгоритм бесшумного кряканья
 class MuteQuack: IQuackBehavior
    {
        
        public void quak()
        {
            Console.Out.WriteLine("Empty Quack!");
        }
    }
}
  //Класс дикой утки 
  public MallarDuck()
        {
            quackBehavior = new Quack();
            flyBehavior = new FlyRocket();
        }

        public override void display()
        {
            Console.Out.WriteLine("I am Mallar Duck!");
        }
    }
  //Класс красноголовой утки
  class RedHeadDuck : Duck
    {
        public RedHeadDuck()
        {
            quackBehavior = new Quack();
            flyBehavior = new FlyRocket();
        }
        public override void display()
        {
            Console.Out.WriteLine("I am Red Head Duck!");
        }
    }

Давайте теперь сделаем класс деревянной утки, для этого сделаем класс-модель утки, которая по умолчанию не умеет ничего делать:
   class ModelDuck : Duck
    {
        public ModelDuck()
        {
            quackBehavior = new MuteQuack();
            flyBehavior = new FlyNoWay();
        }

        public override void display()
        {
            Console.Out.WriteLine("I am model!");
        }
    }
Теперь давайте вызовем все наши классы, а также посмотрим как можно динамически изменять алгоритмы:
class Program
    {
        static void Main(string[] args)
        {
            MallarDuck  MyDuckMallar = new MallarDuck();
            RedHeadDuck MyDuckRedHead = new RedHeadDuck();
           
            //Наша дикая утка
            MyDuckMallar.display();
            MyDuckMallar.performFly();
            MyDuckMallar.performQuack();
            
            //красноголовая утка
            MyDuckRedHead.display();
            MyDuckRedHead.performFly();
            MyDuckRedHead.performQuack();
            
            //модель утки, которой мы поменяли алгоритм 
            //кряканья и алгоритм полета
            ModelDuck myThreeDuck = new ModelDuck();
            myThreeDuck.display();
            myThreeDuck.performFly();
            myThreeDuck.performQuack();

            myThreeDuck.setFlyBehavior(new FlyRocket());
            myThreeDuck.setQuackBehavior(new Quack());

            myThreeDuck.performFly();
            myThreeDuck.performQuack();

            Console.In.ReadLine();

        }
    }

Вот это да! Мы смогли избавиться от дублировния кода, теперь мы можем независимо разрабатывать алгоритмы и присваивать их любым уткам, а также мы смогли уйти от наследования, которое принудительно добавляло все методы во все субклассы!

Подобные связи между двумя классами называются композицией, т.е. поведение не наследуется, а предоставляется правилами выбора.

Принцип проектирования: Отдавайте предпочтение композиции перед наследованием.

Композиция позволяет не только инкапсулировать семейство алгоритмов, но и изменять поведение во время выполнения.
Паттерн СТРАТЕГИЯ определяет семейство алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость. Он позволяет модифицировать алгоритмы независимо от их использования на стороне клиента.