четверг, 29 августа 2013 г.

Абстракция от Sql в C#

Дано:
Имеется база данных с табличкой users(столбцы userID, и userName)

Условие:
Хочется инструмент который позволял бы быстро делать простейшие действия, но при этом был бы достаточно гибким для действий специфических.

Мое решение:
public static class SqlService
{
    private static string connectionString = "CONNECTION_STRING_HERE";

    // это позволит нам быстро создавать соединение
    public static SqlConnection Connection {
        get {
            return new SqlConnection(connectionString);
        }
    }

    // выполняем команду оставляя соединение в исходном состоянии
    private static void myExecute(this SqlCommand command) {
        bool connectionOpened =
            (command.Connection.State == ConnectionState.Open);

        if (!connectionOpened) {
            try {
                command.Connection.Open();
            }
            catch { throw; }
        }

        try {
            command.ExecuteNonQuery();
        }
        catch { throw; }
        finally {
            if (!connectionOpened) {
                command.Connection.Close();
            }
        }
    }

    public static void AddUser(Guid userID,
                               string userName,
                               SqlConnection connection = null) {
        //если соединение не передается в аргументе создаем новое
        SqlConnection con = connection ?? Connection;
        SqlCommand com =
            new SqlCommand("INSERT INTO users(userID, userName)"
                         + " VALUES(@userID, @userName)", con);
        com.Parameters.Add("@userID", SqlDbType.UniqueIdentifier);
        com.Parameters.Add("@userName", SqlDbType.NVarChar, 256);
        com.Parameters["@userID"].Value = userID;
        com.Parameters["@userName"].Value = userName;
        try {
            com.myExecute();
        }
        catch { throw; }
    }

    public static void DeleteUser(Guid userID,
                                  SqlConnection connection = null) {
        SqlConnection con = connection ?? Connection;
        SqlCommand com = new SqlCommand("DELETE FROM users"
                                       + " WHERE userID=@userID", con);
        com.Parameters.Add("@userID", SqlDbType.UniqueIdentifier);
        com.Parameters["@userID"].Value = userID;
        try {
            com.myExecute();
        }
        catch { throw; }
    }
}
Пример использования:
static void Example() {
    Guid newUserID = Guid.NewGuid();

    // простое действие
    // соединение создалось, открылось и закрылось
    SqlService.AddUser(newUserID, "MrSmith");

    // специфичное действие
    using (SqlConnection connection = SqlService.Connection) {
        connection.Open();

        //команда выполнилась, соединение осталось открытым
        SqlService.DeleteUser(newUserID, connection);

        //выполняем любые действия используя то же соединение
        SqlCommand specCom = new SqlCommand(specComText, connection);
        specCom.ExecuteNonQuery();
    }
}

пятница, 9 августа 2013 г.

MODx ERROR: Too many forward attempts.

При использовании ЧПУ в cms MODX может выскочить такая вот неочевидная ошибка "Too many forward attempts", природа её кроется как правило в том что пользователь/администратор/менеджер не указал в настройках станицу которая будет отображаться в случае ошибки.


понедельник, 5 августа 2013 г.

Геолокация IP адресов и злобные хостеры

Случилось однажды такое, что мне надо было прикрутить к сайту определение региона (области/субъекта РФ/тд.) по IP. Первое что пришло в голову - это воспользоваться уже имеющимся сервисом. После некоторых поисков я остановился на этом замечательном сайте http://ipgeobase.ru/

У них имеются 2 реализации.
http://blog.ipgeobase.ru/?p=37
http://blog.ipgeobase.ru/?p=76

Вроде всё просто, Курлом, отправляем адрес, получаем результат, все довольны. Но после часа-полутора возни выяснилось что на хостинге где живёт нужный сайт, провайтер по каким-то причинам запретил Curl'ом ходить по нестандартным портам (а сервисы ipgeobase у нас висят на 8090 и 7020).

Практически моментально отказавшись от использования всяких прокси, было решено сделать всё на стороне клиента, (а что серверу и так нелегко, ещё и ответ курловый ждать =) ).
А чтобы не дёргать по пустякам сервис, результат сохраняется в куках на неделю.

Код решения.
function get_region(){
 //get_cookie - не стандартная функция и не часть jquery =) при отсутствии нужной куки возвращает null
 var region = get_cookie('region');
 if (region !== null) {
  //делаем свои важные дела
  set_region(region);
 }
 //ip нам услужливо печатает сервер.
 var ip = $("#ip").val();
 $.ajax({
  type: "GET",
  url: "http://ipgeobase.ru:7020/geo?ip="+ip,
  dataType: "xml",
  success: function(xml) {
   $(xml).find('ip').each(function(){
    var reg = $(this).find('region').text();
    //делаем свои важные дела
    set_region(reg);
   });
  }
 });
}