среда, 31 августа 2016 г.

Очистка кэша в приложении ASP.Net MVC

Пришлось для приложения asp.net mvc поискать решение для очистки кэша, реализуемого платформой.

Например, такого:

[OutputCache(CacheProfile = CacheHelper.DefaultCacheProfile)]
public ActionResult Index()
{
    var model = new HomeViewModel();
    return View(model);
}

Решение искал долго. Очистку кэша необходимо выполнить для каждой страницы:

Response.Cache.SetNoStore();
Response.Cache.SetNoServerCaching();

foreach (var item in SessionHelper.SiteMap)
{
    HttpResponse.RemoveOutputCacheItem(item.Url);
}

пятница, 19 августа 2011 г.

Com объект для 1С

Возникла необходимость в 1С считать MD5 для файла. Средствами 1С делать это грустно. Было решено сделать Com-объект.

Последовательность действий простая.
Создаём проект Class Library.

Делаем некоторые настройки.

В проекте создаём интерфейс нашего объекта:


using System.Runtime.InteropServices;

namespace MD5HashFile
{
[Guid("3B8D860F-4519-4111-93A0-E6C65982A3D6")]
public interface IHasher
{
[DispId(1)]
string ComputeHash(string path);
}
}

И собственно реализацию:

using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace MD5HashFile
{
[Guid("C024A82B-47FE-42B5-B3A7-8CAB66ADFAAE"), ClassInterface(ClassInterfaceType.None), ProgId("MD5HashFile"), ComVisible(true)]
public class Hasher : IHasher
{
#region Implementation of IHasher

public string ComputeHash(string path)
{
if (File.Exists(path))
{
byte[] retVal;
using (var file = new FileStream(path, FileMode.Open))
{
MD5 md5 = new MD5CryptoServiceProvider();
retVal = md5.ComputeHash(file);
file.Close();
}

var sb = new StringBuilder();
for (var i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
else
{
return null;
}
}

#endregion
}
}

Компилируем. Убеждаемся, что всё работает.

Осталось подписать сборку.
Для этого нужно сгенерировать файл ключа. Можно воспользоваться утилитой sn.exe.
Выполнить в коммандной строке sn -k MD5HashFile_Key.snk
И подписать сборку:

Сборка готова.

Публикуем её в операционной системе:
regasm "d:\MD5HashFile.dll" /codebase

И используем где угодно, например в другом приложении .net.

Console.WriteLine("InputFileName");
var filename = Console.ReadLine();

Type comObjType = Type.GetTypeFromProgID("MD5HashFile");
object comObj = Activator.CreateInstance(comObjType);
var hash = comObjType.InvokeMember("ComputeHash", BindingFlags.InvokeMethod, null, comObj, new object[] { filename});
Console.WriteLine(hash);
Console.ReadLine();

Или в нужном нам 1С. Вызов объекта аналогичен вызову, например, Excel.

Что приятно, использовать можно, как на x86, так и на x64 системах.

среда, 12 мая 2010 г.

EF и хранимые процедуры

При работе с MS EF возникают проблемы при выполнении хранимых процедур, которые возвращают табличное значение. Для работы с такими процедурами есть расширение к EF. Это расширение предоставляет набор методов для материализации объектов из хп.
Ну и пример работы с материализацией.


public List CheckAccess(List baseObjectIds)
{
if (!ConfigSettings.UseSecurity)
{
return baseObjectIds;
}

List result;
using (
DbCommand command = Context.CreateStoreCommand("SP_CheckAccessToObjects",
  CommandType.StoredProcedure,
  new object[]
{
new SqlParameter("objIds",baseObjectIds.ConcatenateIdentifiers())

}))
{
try
{
if (command.Connection.State == ConnectionState.Closed)
{
command.Connection.Open();
}

result = new List(command.Materialize(r => r.Field("ObjId")));
}
catch (Exception ex)
{
Logger.Error(ex);
result = new List();
}
}
return result;
}



четверг, 12 ноября 2009 г.

Утилита для создания ClickOnce приложения

Очень удобно использовать механизм развёртывания приложения ClickOnce.В VS достаточно нажатия одной кнопки, и получаешь полноценно приложение развёртывания, сразу из проекта. Трудности возникают, когда пытаешься развернуть модульное приложение с динамической загрузкой библиотек кода (например, SCSF), Механизм ClickOnce, встроенный в VS не справляется с подобной задачей.
Помочь с решением такой проблемы может утилита Mage. Но использовать её не слишком удобно.
Сам DotNet Framework предоставляет весь необходимый инструментарий, для работы с манифестами. И создать приложение, которое сможет "собирать" установщик ClickOnce достаточно просто. Явные преимущества очевидны:
  • не нужно возиться с командной строкой;
  • механизм создания полностью под вашим контролем;
  • можно применить любые настройки.
После некоторых сомнений я решил изобрести велосипед написать собственное приложение для создания ClickOnce приложений. На мой взгляд, получилось удобно.
Исходные коды см. тут

понедельник, 12 октября 2009 г.

AzMan и SQL Server

Пришлось настраивать хранилище AzMan на SQL Server. Долго не получалось без видимой причины.
Оказалось, что для работы необходимо включить протокол TCP/IP для сервера.

Ну и указать соответствующую строку подключения:

mssql://Driver={SQL Server};Server={localhost};Trusted_Connection={True}/[DataBaseName]/[Storage].

P.S. У нас произошли небольшие изменения и пришлось модифицировать подключение к AzMan с использованием встроенной SQL авторизации. Теперь всё выглядит вот так:

mssql://Driver=SQL Server;Server=localhost;Uid=[username]; pwd=[userpassword];/[DataBaseName]/[Storage]

Странно, но в сети не смог найти информацию о подобном типе подключения. Пришлось придумывать самостоятельно.

пятница, 4 сентября 2009 г.

Синхронизация источников данных, c#

Уже не первый раз за свою практику сталкиваюсь с необходимостью синхронизации таблиц данных, которые хранятся различным образом. Ну, например, основная база данных храниться в СУБД (MS SQL Server, FireBird и т.д.), а некие наборы данных приходят в виде XML файлов.

И так, задача. Данные хранимые в СУБД должны соответсвовать тем данным, которые "пришли" в XML.
Таблица в СУБД имеет структутру Customer(int code, nvarchar name).
Как поступают входны данные, нам собственно и не важно.


Попытка №1
Конечно же, была очень плохой. Я делал 2 прохода по таблицам:
1 проход: перебор записей исходной таблицы, поиск в внешнем наборе.
2 проход: перебор записей внешнего набора, поиск в исходной таблице.
Очень медленно. Лишние переборы.

Попытка №2
Пообщавшись с мировой мудростью, дела пошли лучше.
Условие работы метода - наличие у данных PrimaryKey.
Сортируем исходную таблицу и внешний набор по значению PK (в нашем случае Customer.Code)

//Создаём два индекса для перебора записей
int iNew = 0;
int iCurrent = 0;

//В цикле выбираем 2 записи из таблицы. Нам конечно нужны только их PK.
int newId = (int)newCustomers.Rows[iNew]["Code"];
int currentId = (int)currentCustomers.Rows[iCurrent]["Code"];

//Сравниваем значения PK.
switch(newId.CompareTo(curId))
{
//add new
case -1:  
          Customer customer = new Customer();
           customer.Code = newCustomers.Rows[iNew]["Code"];
           customer.Name = newCustomers.Rows[iNew]["Name"];
           InsertCustomer(customer);
           iNew++;
           break;
//update
case 0:
           currentCustomers.Rows[iCurrent]["Name"] = newCustomers.Rows[iNew]["Name"];
           iNew++;
           iCur++;
           break;
//delete
case 1:
           DeleteCustomer(currentCustomers.Rows[iCurrent]);
           iCur++;
           break;
}
Количество циклов N = newCustomers.Rows U currentCustomers.Rows
Методы InsertCustomer, DeleteCustomer - методы реализующие логику добавления и удаления записей, соответственно.