среда, 31 июля 2013 г.

СРЕДА ВЫПОЛНЕНИЯ .NET FRAMEWORK

1. СРЕДА ВЫПОЛНЕНИЯ .NET FRAMEWORK

   Средой выполнения является CLR (Common Language Runtime) - общеязыковая среда выполнения. Общеязыковая - это значит, что можно писать и на C# и С/С++ и Visual Basic, можно даже свой язык создать и свой компилятор для CLR). Общие механизмы работы этой среды подходят для всех языков программирования, которые ее используют.
 Все языковые компиляторы (CLR-совместимые компиляторы) генерируют IL-код и метаданные (управляемый модуль - PE  файл), с которым в последствии работает CLR.

Сам управляемый модуль состоит из:

  1. Заголовок - обозначает тип файла: GUI, CUI или DLL;
  2. Заголовок CLR - информация для превращение данного модуля в управляемый (расположение метаданных, точку входа и.т.д);
  3. Метаданные - 2 таблицы, описывающие типы данных и их члены;
  4. IL код - CLR компилирует его в машинный код в дальнейшем.
Зачем нужны метаданные? На них работает IntelliSinse, не нужна никакая дополнительная информация о коде, так как все хранится в в исполняемом файле, помогают сборщику мусора и сериализации.

Среда CLR работает со сборками. Сборка - это объединение исполняемых файлов в одну логическую сущность, описанную манифестом. Благодаря сборкам, работающим с управляемым кодом, нет необходимости в реестре, как в случает с неуправляемым кодом.
Сборка разбивает управляемые модули и ресурсные файлы.

Сборка представляет собой dll файл или приложение. В процессе разработки скорее всего будет использоваться язык высокого уровня, например C#, который не использует в полную мощь среду CLR. Для использования каких-то особенный функций можно писать часть приложения на ассемблере IL

Перед выполнением JIT компиляторы переводят в машинный код IL код. При этом CLR вызывает JIT компилятор только при первой компиляции типа. В дальнейшем это уже не потребуется, так как все будет загружено в память.

Разработка ORACLE PL/SQL - ASP MVC 3- JavaScript

Всем привет! 
Хотелось поделиться со всеми своими наработками веб-приложений. Я не являюсь гуру или даже близким к нему, но как-то получилось так, что я искал на чем же мне начать писать веб приложения, и вот труды моих поисков)

Первым, с чем я познакомился, был девэкспресс. Я обрадовался, и думал что вот оно, создание приложения как в веб формс (перетаскиваем формочки и никаких проблем), но сразу наткнулся на кучу проблем. Например, девэкспресс начинает жутко тормозить при работе с большими таблицами, и как-то непонято было как оно внутри работает. Плюс куча настроек, которые я вытаскивал из примеров и форумов, меня начали выбешивать, поэтому плюнов на все, я решил поискать что-то другое.

НО! Девэкспресс очень крутая штука (ввиду своей криворукости не смог высидеть прозрение), фактически можно использую минимум знаний css javascript и htlm - сварганить красивые формы, и главное, очень быстро! Плюс подключив, XPO можно отгородиться от DML (Select Insert Update Delete), а также заморочки с транзакциями и всякой лабудой.

Вообщем я никогда не любил ORM, как-то я люблю Oracle и все его фишки, и отказывать от них мне не хотелось, ну страшно мне смотреть на то, как что-то терзает базу данных непонятными запросами, еще и план непонятно какой. 
К чему я пришел в итоге?

ORM я решил писать свой, точнее его ORM назвать я думаю нельзя) Это повсеместно используемый подход.

Все манипуляции с БД я делал PL/SQL процедурами, точнее все запросы и DML я вынес в хранимки. Так, с первым уровнем решили. Дальше сервер приложений.


Сервер приложений.....Какой? Я выбрал IIS, так как очень удобна в стеке мелкософта реализована SSO. Пользователь ввел логин в виндоус и спокойно работает с приложением без дополнительных заморочек с авторизацией. Ну да, глуповат я для линуксов и апатчей. 
А может нужно было пойти J2EE путем? Oracel Java отличная связка, с учетом что это все теперь единое целое. 
Я попробовал: Servet, JSP , JSF , ADF. Пробовал на GlassFish и Weblogic, подключая при этом EJB и даже пробовал Hibernate. Java велика! Кучи фреймворков, кучи xml связок между разными фреймворками. Для больших решений, это было бы оправдано, но я работаю один, даже командной разработки толком нет никакой, поэтому я все выкинул. Кстати: Servet, JSP , JSF меня насторожили тем, что все технологии очень медленно развиваются и концепция последнего мне совсем не понравилась. 

Стек LAMP (Linux-Apache-MySQL-PHP ) не подошел по корпоративным принципам, да и используется он по большей части для создания сайтов.

Ну так вот IIS, какая Технология разработки? Web Forms? Нет! Опять от меня прячут все! Дайте код посмотреть!))
ASP MVC! Вот это красота) Паттерн MVC мне всегда нравился - все наглядно и полный контроль.

На чем писать клиентскую часть?
JS - фреймворки, все! не смогут обеспечить работу с большими таблицами (группировки, сортировки и.т.д) так как они тащут все исходные данные на клиент, и обрабатывают их средствами браузера. Как писать сами html - страницы? Хелперы? Опять получается некое скрытие html.

Вот оно: javascript, css, html5, jQuery, Twitter Bootstrap!

Что в итоге мне было нужно? Фреймворк, работающий с ораклом, он должен быть открыт на модификацию, и я хочу полный контроль происходящего. 
Пришлось писать свой. Которым я хочу поделиться.
Принцип его работы очень прост:
1) Пакет оракла содержит функции для удаления, обновления, вставки и извлечения данных.
2) На asp MVC есть класс и ORM класс, которые выполняют вызов функций Oracle. Контроллеры посылают JSON на клиент.
3) Клиент принимает JSON и перестраивает динамечески таблицу

Тут первая часть, делаем обычную таблицу

Разработка ORACLE PL/SQL - ASP MVC 3- JavaScript Часть 1. Создание простой таблицы

Небольшой обзор технологий я уже сделал в предыдущей статье, здесь я хотел бы показать как я реализовал свой подход:

Создание хранимых процедур
Справочник регионов.
Пакет:

create or replace package admin_REGION_V01 as

    function f_sel_REGION return tab_select_REGION pipelined;

    function f_upd_REGION(p_REGION_ID        in NUMBER,
                                                p_REGION_NAME in VARCHAR2) return varchar2;

    function f_ins_REGION( p_REGION_NAME in VARCHAR2) return varchar2;

    function f_del_REGION(p_REGION_ID in NUMBER) return varchar2;

end admin_REGION_V01;


Тело пакета:

create or replace package body admin_REGION_V01 as

    function f_sel_REGION return tab_select_REGION  pipelined
    as
        l_t_select_REGION t_select_REGION;
    begin
       l_t_select_REGION:= t_select_REGION(0,'');
       for C in (select
                    REGION_ID,REGION_NAME
                from REGION
       )
       loop
         l_t_select_REGION.REGION_ID:= C.REGION_ID;
         l_t_select_REGION.REGION_NAME:= C.REGION_NAME;

       pipe row (l_t_select_REGION);

       end loop;

    return;
    end f_sel_REGION;

    function f_upd_REGION( p_REGION_ID   in NUMBER,
                           p_REGION_NAME in VARCHAR2) return varchar2
    as
        pragma autonomous_transaction;
        my_errm VARCHAR2(32000);
    begin
       update REGION
       set  REGION_NAME = p_REGION_NAME
       where REGION_ID= p_REGION_ID;

      commit;
     return 'REGION:' || p_REGION_NAME ||' was success updated';
    exception when others then
              my_errm := SQLERRM;
              rollback;
              return my_errm;
    end f_upd_REGION;

    function f_ins_REGION( p_REGION_NAME   in VARCHAR2) return varchar2
    as
        pragma autonomous_transaction;
        my_errm VARCHAR2(32000);
    begin
       insert into REGION
       (
         REGION_ID,
         REGION_NAME
       )
       values (
         seq_groups_id.nextval,
         p_REGION_NAME);
      commit;
     return 'REGION:' || p_REGION_NAME|| 'was success inserted';
    exception when others then
              my_errm := SQLERRM;
              rollback;
              return my_errm;
    end f_ins_REGION;

    function f_del_REGION(p_REGION_ID   in NUMBER) return varchar2
    as
       pragma autonomous_transaction;
       my_errm VARCHAR2(32000);
    begin
       delete from REGION
       where REGION_ID =p_REGION_ID;
       commit;
     return 'REGION: '|| p_REGION_ID||' was success deleted';
    exception when others then
        my_errm := SQLERRM;
        rollback;
        return my_errm;
    end f_del_REGION;
    
end admin_REGION_V01;


Тут собственно я обернул все необходимые DML для работы приложения с таблицей.

Дальше в ASP MVC делаем класс, фактически это все колонки Вашей таблицы:


namespace TEST.Models.OracleORM.classes
{
public class Region
{
public int RegionRegionId { set; get; }
public string RegionRegionName { set; get; }

public Region() { }
}
}


Далее ORM класс, который будет вызывать хранимые процедуры:


using System;
using System.Collections.Generic;
using COMMON.Oracle;
using Erequest3AdminTool.Models.OracleORM.classes;

namespace Erequest3AdminTool.Models.OracleORM
{
    public class RegionIUDS
    {
        private static String RegionSelect = @" select    region_id           F01
                                                                                            ,region_name     F02                                                        
                                               from table(admin_region_v01.f_sel_region())";

        private static String RegionUpdate = @"select admin_region_v01.f_upd_region(  p_REGION_ID   =>  &p_REGION_ID
                                                                                     ,p_REGION_NAME => '&p_REGION_NAME') results from dual";

        private static String RegionInsert = @"select admin_region_v01.f_ins_region( p_REGION_NAME => '&p_REGION_NAME') results from dual";

        private static String RegionDelete = @"select admin_region_v01.f_del_region(p_REGION_ID   =>&p_REGION_ID ) results from dual";

       
        public static List<Region> SelectRegion()
        {
            List<Region> result = new List<Region>();
            try
            {
                foreach (OracleField row in OracleLib.setExecuteSelect(RegionSelect))
                {
                    result.Add(new Region()
                    {
                        RegionRegionId = Convert.ToInt32(row.F01),
                        RegionRegionName = row.F02
                    });
                }
            }
            catch
            {
                throw;
            }

            return result;
        }

      public static string UpdateRegion(Region Region)
        {
            string result = "";
            try
            {
                String l_sql = RegionUpdate;

                l_sql = l_sql.Replace("&p_REGION_ID", Convert.ToString(Region.RegionRegionId));
                l_sql = l_sql.Replace("&p_REGION_NAME", Region.RegionRegionName);
              

                result = OracleLib.setExecuteIUD(l_sql);
            }
            catch
            {
                throw;
            }
            return result;
        }

      
        public static string InsertRegion(Region Region)
        {
            string result = "";
            try
            {
                String l_sql = RegionInsert;
               
                l_sql = l_sql.Replace("&p_REGION_NAME", Region.RegionRegionName);

                result = OracleLib.setExecuteIUD(l_sql);
            }
            catch
            {
                throw;
            }
            return result;
        }

       
        public static string DeleteRegion(int RegionRegionId)
        {
            string result = "";
            try
            {
                String l_sql = RegionDelete;

                l_sql = l_sql.Replace("&p_REGION_ID", Convert.ToString(RegionRegionId));

                result = OracleLib.setExecuteIUD(l_sql);
            }
            catch
            {
                throw;
            }
            return result;
        }
    }
}

Смысл я думаю понятен, просто перезаписываем переменные какими-то значениями, которые передаются из контроллера.

Далее контроллер:


namespace Erequest3AdminTool.Controllers
{
    public class RegionController : Controller
    {
        /// <summary>
        /// Полная страница для отображения
        /// </summary>       
        public ActionResult RegionShowPage()
        {
            return View("RegionTable");
        }

        /// <summary>
        /// Передает список всех пользователей через JSON
        /// </summary>       
        public ActionResult RegionSelect()
        {          
            return Json(RegionIUDS.SelectRegion(), JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// Обновить данные о Region
        /// </summary>
        /// <param name="Region">JSON, содержит информацию для обновления</param>
        [HttpPost]
        public ActionResult RegionUpdate(Region Region)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    string results = RegionIUDS.UpdateRegion(Region);

                    if (results.Contains("ORA"))
                    {
                        return PartialView("~/Views/Shared/error.cshtml", results);
                    }
                    else
                    {
                        return PartialView("~/Views/Shared/done.cshtml", results);
                    }
                }
                else
                {
                    return PartialView("~/Views/Shared/error.cshtml", "RegionUpdate invalid Model");
                }
            }
            catch (Exception e)
            {
                return View("~/Views/Shared/error.cshtml", e.Message);
            }
        }

        /// <summary>
        /// Добавление данных в Region
        /// </summary>
        /// <param name="Region">JSON, содержит информацию для обновления</param>
        [HttpPost]
        public ActionResult RegionInsert(Region Region)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    string results = RegionIUDS.InsertRegion(Region);

                    if (results.Contains("ORA"))
                    {
                        return PartialView("~/Views/Shared/error.cshtml", results);
                    }
                    else
                    {
                        return PartialView("~/Views/Shared/done.cshtml", results);
                    }
                }
                else
                {
                    return PartialView("~/Views/Shared/error.cshtml", "RegionInsert invalid Model");
                }
            }
            catch (Exception e)
            {
                return View("~/Views/Shared/error.cshtml", e.Message);
            }
        }

        /// <summary>
        /// Удаление данных в Region
        /// </summary>
        /// <param name="Region">JSON, содержит информацию для удаления</param>
        [HttpPost]
        public ActionResult RegionDelete(string RegionRegionId)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    string results = RegionIUDS.DeleteRegion(Convert.ToInt32(RegionRegionId));

                    if (results.Contains("ORA"))
                    {
                        return PartialView("~/Views/Shared/error.cshtml", results);
                    }
                    else
                    {
                        return PartialView("~/Views/Shared/done.cshtml", results);
                    }
                }
                else
                {
                    return PartialView("~/Views/Shared/error.cshtml", "RegionDelete invalid Model");
                }
            }
            catch (Exception e)
            {
                return View("~/Views/Shared/error.cshtml", e.Message);
            }
        }

    }

}

Фактически контроллеры принимают JSON и вызывают методы класса ORM.
И наконец View:



<!--load js-->

<script src="@Url.Content("~/Content/JavaScript/JsORM/Region/js/RegionTable.js")"></script>



<div class="span4">
   <h4>Regions</h4>
   <div style="overflow-x: auto; width: 100%" id="allRegions"></div>
</div>


Тут все происходит в RegionTable.js:

var tableRegionDescription = {
TableID: 'Region'
, ContentDiv: '#allRegions'
, Columns: [{ ColumnName: "Region Name", ColumnID: "RegionRegionName", IsSort: 1, ColumnType: 'text', IsVisible: 'true', IsPK: 'false' }
,{ ColumnName: "Id", ColumnID: "RegionRegionId", IsSort: 0, ColumnType: 'text', IsVisible: 'false', IsPK: 'true' }]
, DeleteController: '/Region/RegionDelete'
, InsertController: '/Region/RegionInsert'
, UpdateController: '/Region/RegionUpdate'
, SelectController: '/Region/RegionSelect'
, tableData: []
};

$(document).ready(function () {

//создаем заголовок для таблицы и саму таблицу без данных
$(tableRegionDescription.ContentDiv).createTableHead(tableRegionDescription);

//заполняем таблицу данными
$().createTable(tableRegionDescription);

});


И вот что мы получаем:

region

По поводу параметров:

TableID: - идентификатор таблицы, которая будет добавлена
, ContentDiv: - ID DIV, куда добавлять таблицу
, Columns: массив колонок таблицы
ColumnName - имя отображаемой колонки
ColumnID - идентификатор колонки
IsSort - включить сортировку
ColumnType - тип колонки
IsVisible - отображать в таблице или нет
IsPK - колонка, которая является первичным ключом, необходимо будет при удаление данных из таблицы
, SelectController: - контроллер, которые будет получать данные
, tableData: [] - массив, содержащий данные, которые будут загружены из SelectController