Захотелось быстро поработать с Oracle без кучи фреймворковских библиотек. Создаем любой статический класс и добавляем метод:
/// <summary>
/// Обернуть таблицу в нужный класс
/// </summary>
/// <typeparam name="T">Класс, в который обертываем</typeparam>
/// <param name="table">Таблица данных</param>
/// <returns></returns>
public static List<T> DataTableToList<T>(DataTable table) where T : class, new()
{
try
{
List<T> list = new List<T>();
foreach (var row in table.AsEnumerable())
{
T obj = new T();
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
object safeValue = (row[prop.Name] == null) ? null : Convert.ChangeType(row[prop.Name], t);
propertyInfo.SetValue(obj, safeValue, null);
}
catch
{
continue;
}
}
list.Add(obj);
}
return list;
}
catch
{
return null;
}
}
Далее добавляем следующий метод. Если у нас в классе есть свойство, то нужно проверить есть ли такое поле в базе данных.
/// <summary>
/// Проверка свойства в БД
/// </summary>
/// <param name="prop">Имя свойства</param>
/// <param name="TBLNAME">Таблица в БД</param>
/// <param name="OWNER">Схема</param>
/// <returns></returns>
public static bool CheckProperty(PropertyInfo prop, string TBLNAME, string OWNER)
{
bool res = false;
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE OWNER = '" + OWNER + "' AND TABLE_NAME = '" + TBLNAME + "' AND COLUMN_NAME = '" + prop.Name + "'";
using (OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (reader.HasRows)
{
res = true;
}
}
}
}
return res;
}
Далее создаем метод на все случаи жизни (SELECT,INSERT,UPDATE,DELETE).
/// <summary>
/// Универсальная функция преобразования данных
/// </summary>
/// <typeparam name="T">Класс</typeparam>
/// <param name="mode">Режим (0-select,1-insert,2-update,3-delete)</param>
/// <param name="TBLNAME">Таблица в БД</param>
/// <param name="obj">Экземпляр класса</param>
/// <param name="ST">Параметр успешного выполнения</param>
/// <param name="MES">Сообщение об ошибке</param>
/// <param name="tb">Таблица данных</param>
/// <param name="WHERECLAUSE">Условие</param>
/// <param name="FIELDLIST">Набор полей</param>
/// <param name="SEQNAME">Имя последовательности</param>
/// <param name="ROWNUM">Количество строк по умолчанию все</param>
/// <param name="OWNER">Схема</param>
/// <returns></returns>
public static bool GetInsertUpdateDelete<T>(int mode, string TBLNAME, T obj, out int ST, out string MES, out DataTable tb, string WHERECLAUSE = null, string FIELDLIST = null, string SEQNAME = null, int ROWNUM = -1, string OWNER = "NSKFND")
{
ST = 0;
MES = "";
tb = new DataTable();
bool res = false;
switch (mode)
{
case 0:
var get = "SELECT ";
if (string.IsNullOrEmpty(FIELDLIST))
{
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
if (CheckProperty(propertyInfo, TBLNAME, OWNER))
{
get += propertyInfo.Name + ",";
}
}
catch
{
continue;
}
}
get = get.Remove(get.Length - 1, 1)
+ " FROM " + OWNER + "." + TBLNAME
+ (string.IsNullOrEmpty(WHERECLAUSE) ? (ROWNUM == -1 ? "" : " WHERE ROWNUM < " + ROWNUM.ToString()) : " WHERE " + WHERECLAUSE
+ (ROWNUM == -1 ? "" : " AND ROWNUM < " + ROWNUM.ToString()));
}
else
{
get += FIELDLIST
+ " FROM " + OWNER + "." + TBLNAME
+ (string.IsNullOrEmpty(WHERECLAUSE) ? (ROWNUM == -1 ? "" : " WHERE ROWNUM < " + ROWNUM.ToString()) : " WHERE " + WHERECLAUSE
+ (ROWNUM == -1 ? "" : " AND ROWNUM < " + ROWNUM.ToString()));
}
try
{
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = get;
using (OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (reader.HasRows)
{
tb.Load(reader);
}
res = true;
}
}
}
}
catch (Exception e)
{
ST = -1;
MES = e.Message;
tb = null;
}
break;
case 1:
var insertfld = "INSERT INTO " + OWNER + "." + TBLNAME + " (";
var insertval = " VALUES(";
tb = null;
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
if (CheckProperty(propertyInfo, TBLNAME, OWNER))
{
insertfld += propertyInfo.Name + ",";
insertval += ":" + propertyInfo.Name + ",";
}
}
catch
{
continue;
}
}
var transaction = insertfld.Remove(insertfld.Length - 1, 1) + ")" + insertval.Remove(insertval.Length - 1, 1) + ")";
try
{
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = transaction;
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
if (CheckProperty(propertyInfo, TBLNAME, OWNER))
{
if (propertyInfo.Name == "ID")
{
var NEXT = GetSeq(SEQNAME,OWNER);
propertyInfo.SetValue(obj, Convert.ChangeType(NEXT, propertyInfo.PropertyType), null);
ST = (int)NEXT;
}
var val = propertyInfo.GetValue(obj, null);
try
{
var d = DateTime.ParseExact(val.ToString(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
OracleParameter dt = new OracleParameter(propertyInfo.Name, OracleDbType.TimeStamp, ParameterDirection.Input);
dt.Value = d;
cmd.Parameters.Add(dt);
}
catch
{
try
{
var d = DateTime.ParseExact(val.ToString(), "dd.MM.yyyy", System.Globalization.CultureInfo.InvariantCulture);
OracleParameter dt = new OracleParameter(propertyInfo.Name, OracleDbType.Date, ParameterDirection.Input);
dt.Value = d;
cmd.Parameters.Add(dt);
}
catch
{
cmd.Parameters.Add(propertyInfo.Name, val);
}
}
}
}
catch
{
continue;
}
}
cmd.ExecuteNonQuery();
res = true;
}
}
}
catch (Exception e)
{
ST = -1;
MES = e.Message;
}
break;
case 2:
var update = "UPDATE " + OWNER + "." + TBLNAME + " SET ";
tb = null;
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
if (CheckProperty(propertyInfo, TBLNAME, OWNER))
{
update += propertyInfo.Name + " = :" + propertyInfo.Name + ",";
}
}
catch
{
continue;
}
}
update = update.Remove(update.Length - 1, 1) + " WHERE " + WHERECLAUSE;
try
{
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = update;
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
if (CheckProperty(propertyInfo, TBLNAME, OWNER))
{
if (propertyInfo.Name == "ID")
{
var id = propertyInfo.GetValue(obj, null);
ST = int.Parse(id.ToString());
}
var val = propertyInfo.GetValue(obj, null);
try
{
var d = DateTime.ParseExact(val.ToString(), "dd.MM.yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
OracleParameter dt = new OracleParameter(propertyInfo.Name, OracleDbType.TimeStamp, ParameterDirection.Input);
dt.Value = d;
cmd.Parameters.Add(dt);
}
catch
{
try
{
var d = DateTime.ParseExact(val.ToString(), "dd.MM.yyyy", System.Globalization.CultureInfo.InvariantCulture);
OracleParameter dt = new OracleParameter(propertyInfo.Name, OracleDbType.Date, ParameterDirection.Input);
dt.Value = d;
cmd.Parameters.Add(dt);
}
catch
{
try
{
var d = DateTime.ParseExact(val.ToString(), "dd.MM.yyyy H:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
OracleParameter dt = new OracleParameter(propertyInfo.Name, OracleDbType.TimeStamp, ParameterDirection.Input);
dt.Value = d;
cmd.Parameters.Add(dt);
}
catch
{
cmd.Parameters.Add(propertyInfo.Name, val);
}
}
}
}
}
catch
{
continue;
}
}
cmd.ExecuteNonQuery();
res = true;
}
}
}
catch (Exception e)
{
ST = -1;
MES = e.Message;
}
break;
case 3:
var delete = "DELETE FROM " + OWNER + "." + TBLNAME + " WHERE " + WHERECLAUSE;
try
{
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = delete;
cmd.ExecuteNonQuery();
res = true;
}
}
}
catch (Exception e)
{
ST = -1;
MES = e.Message;
}
break;
}
return res;
}
Ну вот и все. Использование...
public partial class LookUpClass
{
public string DESCRIPTION { get; set; }
}
[MetadataType(typeof(Rules_Metadata))]
public partial class Rules
{
public decimal ID { get; set; }
public string NAME { get; set; }
public string CODE { get; set; }
public string DESCRIPTION { get; set; }
}
internal partial class Rules_Metadata
{
[DisplayName("Идентификатор")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public decimal ID { get; set; }
[DisplayName("Наименование")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public string NAME { get; set; }
[DisplayName("Код")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public string CODE { get; set; }
[DisplayName("Примечание")]
public string DESCRIPTION { get; set; }
}
[MetadataType(typeof(RulesDetails_Metadata))]
public partial class RulesDetails
{
public decimal ID { get; set; }
public Nullable<decimal> RULEID { get; set; }
public Nullable<decimal> REPFOLDER { get; set; }
public Nullable<decimal> REPREPORT { get; set; }
public decimal ACTIVE { get; set; }
public string MODIFYDATE { get; set; }
public decimal MODIFYBY { get; set; }
public string DESCRIPTION { get; set; }
}
internal partial class RulesDetails_Metadata
{
[DisplayName("Идентификатор")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public decimal ID { get; set; }
[DisplayName("Правило")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public Nullable<decimal> RULEID { get; set; }
[DisplayName("Папка отчета")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public Nullable<decimal> REPFOLDER { get; set; }
[DisplayName("Отчет")]
public Nullable<decimal> REPREPORT { get; set; }
[DisplayName("Активный")]
public decimal ACTIVE { get; set; }
[DisplayName("Дата изменения")]
[DataType(DataType.Date)] //DateTime для времени
[DisplayFormat(DataFormatString = "dd.MM.yyyy ")] //hh:mm для времени
[Required(ErrorMessage = "Поле должно быть заполнено")]
public string MODIFYDATE { get; set; }
[DisplayName("Автор")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public decimal MODIFYBY { get; set; }
[DisplayName("Примечание")]
public string DESCRIPTION { get; set; }
}
[MetadataType(typeof(Permis_Metadata))]
public partial class Permis
{
public decimal ID { get; set; }
public Nullable<decimal> STUFFID { get; set; }
public Nullable<decimal> USERID { get; set; }
public Nullable<decimal> RULEID { get; set; }
public decimal ACTIVE { get; set; }
public string MODIFYDATE { get; set; }
public decimal MODIFYBY { get; set; }
public string DESCRIPTION { get; set; }
}
internal partial class Permis_Metadata
{
[DisplayName("Идентификатор")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public decimal ID { get; set; }
[DisplayName("Должность")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public Nullable<decimal> STUFFID { get; set; }
[DisplayName("Пользователь")]
public Nullable<decimal> USERID { get; set; }
[DisplayName("Правило")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public Nullable<decimal> RULEID { get; set; }
[DisplayName("Активный")]
public decimal ACTIVE { get; set; }
[DisplayName("Дата изменения")]
[DataType(DataType.Date)] //DateTime для времени
[DisplayFormat(DataFormatString = "dd.MM.yyyy ")] //hh:mm для времени
[Required(ErrorMessage = "Поле должно быть заполнено")]
public string MODIFYDATE { get; set; }
[DisplayName("Автор")]
[Required(ErrorMessage = "Поле должно быть заполнено")]
public decimal MODIFYBY { get; set; }
[DisplayName("Примечание")]
public string DESCRIPTION { get; set; }
}
public class FReportPermissionController : CController
{
[PartialAuthorize]
public ActionResult RuleEdit_(decimal? id)
{
var ST = 0;
var MES = "";
DataTable pseudo = null;
if (ODDA.GetInsertUpdateDelete(0, "SME_RULES", new Rules(), out ST, out MES, out pseudo, "ID = " + id.ToString()))
{
var model = ODDA.DataTableToList<Rules>(pseudo);
return PartialView(model[0]);
}
else
{
return NotAjaxFormAlert("getNewTost('" + MES + "','error');");
}
}
[HttpPost]
[PartialAuthorize]
public ActionResult RuleEdit_(Rules model)
{
var ST = 0;
var MES = "";
DataTable pseudo = null;
if (ModelState.IsValid)
{
ODDA.GetInsertUpdateDelete(2, "SME_RULES", model, out ST, out MES, out pseudo, "ID = " + model.ID.ToString());
return InvertCheckTransactionState(ST, MES, 2, "/FReportPermission/Index?IdName=" + ST.ToString());
}
else
{
return PartialView(model);
}
}
}
Ну и вьюшка на метод public ActionResult RuleEdit_(decimal? id)
@* Модальная форма редактирования правила *@
@model FFI.Controllers.Rules
<div class="modal-header">
@* Копка в углу формы для ее закрытия *@
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span>
</button>
@* Заголовок модальной формы *@
<h4 class="modal-title">@MyHelpers.GetTranslation("Редактировать правило доступа")</h4>
</div>
@using (Html.FFIForm("/FReportPermission/RuleEdit_", "#valmodal", OnBegin: "buttonLadda.ladda('start');", OnSuccess: "ReloadPartial(); RefreshButtonStateModal(validationModal);", cssclass: "newValidateUpdateRule"))
{
<div class="modal-body form-horizontal formPut clearfix">
@Html.FFInput(model => model.ID, lableClass: "col-lg-2 col-md-2 col-sm-4 col-xs-4", secondDivClass: "col-lg-10 col-md-10 col-sm-8 col-xs-8", forCreate:false, ForEdit:false)
@Html.FFInput(model => model.NAME, lableClass: "col-lg-2 col-md-2 col-sm-4 col-xs-4", secondDivClass: "col-lg-10 col-md-10 col-sm-8 col-xs-8")
@Html.FFInput(model => model.CODE, lableClass: "col-lg-2 col-md-2 col-sm-4 col-xs-4", secondDivClass: "col-lg-10 col-md-10 col-sm-8 col-xs-8")
@Html.FFInput(model => model.DESCRIPTION, lableClass: "col-lg-2 col-md-2 col-sm-4 col-xs-4", secondDivClass: "col-lg-10 col-md-10 col-sm-8 col-xs-8")
</div>
<div class="modal-footer">
<button type="button" class="btn btn-white evBtnCancelAll" data-dismiss="modal">@MyHelpers.GetTranslation("Отмена")</button>
@* Элемент лада кнопки *@
<button type="submit" class="btn btn-primary ladda-button ladda-button-submit evBtnUpdateAll" data-style="expand-right">@MyHelpers.GetTranslation("Обновить")</button>
</div>
}
Вот еще несколько вспомогательных методов для полноты картины
/// <summary>
/// Получить уникальный ID с любого секвенсера
/// </summary>
/// <param name="seqname">Имя последовательности</param>
/// <param name="OWNER">Схема</param>
/// <returns></returns>
public static decimal GetSeq(string seqname, string OWNER)
{
decimal res = 0;
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT " + OWNER + "." + seqname + ".NEXTVAL FROM DUAL";
using (OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (reader.HasRows)
{
reader.Read();
res = decimal.Parse(reader[0].ToString());
}
}
}
}
return res;
}
/// <summary>
/// Получить REF_CURSOR из любой процедуры в виде таблицы
/// </summary>
/// <param name="refproc">Процедура в БД</param>
/// <param name="param">Список параметров</param>
/// <param name="OWNER">Схема</param>
/// <returns></returns>
public static DataTable ExecuteProcForRefCursor(string refproc, List<OracleParameter> param, string OWNER = "NSKFND")
{
DataTable tbl = new DataTable();
using (var conn = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandText = OWNER + "." + refproc;
cmd.CommandType = CommandType.StoredProcedure;
foreach (var item in param)
{
cmd.Parameters.Add(item);
}
using (OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (reader.HasRows)
{
tbl.Load(reader);
}
}
}
}
return tbl;
}
Хотелось бы узнать мнение сообщества по данной теме. Для поддержания EF(EntityFramework) нужно тратить много времени, конечно он хорош, когда в БД(База данных) таблиц не более 200. Если же больше он становится просто обузой, с которой очень трудно работать. Выше представлена моя альтернатива...Удачи всем!
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Условие: Имеется несколько Database Project проектовВ каждом своя схема одной БД