2

Я использую архитектуру арфы S #, кто-нибудь нашел способ доступа к SQL Azure Federations с ней?SQL Azure Federation с архитектурой S # arp

Я знаю, что следующая транзакция должна выполняться вне транзакции, поскольку SQL Azure не разрешает «использовать федерацию» в транзакции.

use Federation CustomerFederation (CustomerID=2) with reset, filtering=on 
GO 
<some sql statement...> 
GO 

Существует еще один пост здесь, что показывает пример с создания пользовательского класса NHibernate Session, но как это может быть достигнуто/удлиняться S # Arp Architecture?

Я также знаю, что в SQL Azure федерации есть другие возможности sharding, такие как NHibernate.Shards или многоуровневое расширение архитектуры S # arp, но, пожалуйста, продолжайте отвечать на вопрос, а не на другие варианты.

Я знаю, что я не единственный человек, использующий архитектуру S # arp и SQL Azure Federations, и Google не предоставил многого, поэтому, если кто-либо из них нашел решение, то, пожалуйста, поделитесь.

ответ

2

Поскольку никто еще не ответил на мой пост, я отвечаю на него после нескольких дней исследований. Я смог интегрироваться с аркой S # с 1 интерфейсом и 3 классами (я надеялся, что это будет из коробки решение?).

Приведенный ниже код может быть скопирован и вставлен в любое приложение, и он должен просто работать. Единственным исключением является класс FederationSessionHelper. Это относится к каждому приложению, поскольку вы получаете информацию, которая может измениться. У меня есть раздел настроек приложения в моем web.config, у которого есть имя федерации и т. Д. Кроме того, когда пользователь аутентифицируется, я анализирую корневой URL-адрес, с которого они отправляются, затем запрашивает корень федерации, чтобы узнать, кто их арендатор (у меня есть пользовательская таблица арендаторов, которую я создал). Затем я размещаю идентификатор арендатора в сеансе под ключом «FederationKeyValue_Key», который затем будет использоваться в классе FederationSession для создания оператора Use Federation.

/// <summary> 
/// Interface used to retrieve app specific info about your federation. 
/// </summary> 
public interface IFederationSessionHelper 
{ 
    string ConnectionString { get; } 
    string FederationName { get; } 
    string DistributionName { get; } 
    string FederationKeyValue { get; } 
} 

/// <summary> 
/// This is were you would get things specific for your application. I have 3 items in the web.config file and 1 stored in session. You could easily change this to get them all from the repository or wherever meets the needs of your application. 
/// </summary> 
public class FederationSessionHelper : IFederationSessionHelper 
{ 
    private const string ConnectionStringKey = "ConnectionString_Key"; 
    private const string FederationNameKey = "FederationName_Key"; 
    private const string DistributionNameKey = "DistributionName_Key"; 
    private const string FederationKeyValueKey = "FederationKeyValue_Key"; 

    public string ConnectionString { get { return ConfigurationManager.ConnectionStrings[ConnectionStringKey].ConnectionString; } } 
    public string FederationName { get { return ConfigurationManager.AppSettings[FederationNameKey]; } } 
    public string DistributionName { get { return ConfigurationManager.AppSettings[DistributionNameKey]; } } 

    //When user authenitcates, retrieve key value and store in session. This will allow to retrieve here. 
    public string FederationKeyValue { get { return Session[FederationKeyValueKey]; } }  
} 

/// <summary> 
/// This is were the magic begins and where the integration with S#arp occurs. It manually creates a Sql Connections and adds it the S#arps storage. It then runs the Use Federation command and leaves the connection open. So now when you use an NhibernateSession.Current it will work with Sql Azure Federation. 
/// </summary> 
public class FederationSession : IDisposable 
{ 
    private SqlConnection _sqlConnection; 

    public void Init(string factoryKey, 
         string federationName, 
         string distributionName, 
         string federationKeyValue, 
         bool doesFilter, 
         string connectionString) 
    { 
     var sql = string.Format("USE FEDERATION {0}({1} = '{2}') WITH RESET, FILTERING = {3};", federationName, distributionName, federationKeyValue, (doesFilter) ? "ON" : "OFF"); 
     _sqlConnection = new SqlConnection(connectionString); 

     _sqlConnection.Open(); 
     var session = NHibernateSession.GetSessionFactoryFor(factoryKey).OpenSession(_sqlConnection); 
     NHibernateSession.Storage.SetSessionForKey(factoryKey, session); 

     var query = NHibernateSession.Current.CreateSQLQuery(sql); 
     query.UniqueResult(); 
    } 

    public void Dispose() 
    { 
     if (_sqlConnection != null && _sqlConnection.State != ConnectionState.Closed) 
      _sqlConnection.Close(); 
    } 
} 

/// <summary> 
/// This was just icing on the cake. It inherits from S#arps TransactionAttribute and calls the FederationSession helper to open a connection. That way all you need to do in decorate your controller with the newly created [FederationTransaction] attribute and thats it. 
/// </summary> 
public class FederationTransactionAttribute : TransactionAttribute 
{ 
    private readonly string _factoryKey = string.Empty; 
    private bool _doesFilter = true; 

    /// <summary> 
    ///  When used, assumes the <see cref = "factoryKey" /> to be NHibernateSession.DefaultFactoryKey 
    /// </summary> 
    public FederationTransactionAttribute() 
    { } 

    /// <summary> 
    ///  Overrides the default <see cref = "factoryKey" /> with a specific factory key 
    /// </summary> 
    public FederationTransactionAttribute(string factoryKey = "", bool doesFilter = true) 
     : base(factoryKey) 
    { 
     _factoryKey = factoryKey; 
     _doesFilter = doesFilter; 
    }   

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var federationSessionHelper = ServiceLocator.Current.GetInstance<IFederationSessionHelper>(); 
     var factoryKey = GetEffectiveFactoryKey(); 
     new FederationSession().Init(factoryKey, 
             federationSessionHelper.FederationName, 
             federationSessionHelper.DistributionName, 
             federationSessionHelper.FederationKeyValue, 
             _doesFilter, 
             federationSessionHelper.ConnectionString); 

     NHibernateSession.CurrentFor(factoryKey).BeginTransaction(); 
    } 

    private string GetEffectiveFactoryKey() 
    { 
     return String.IsNullOrEmpty(_factoryKey) ? SessionFactoryKeyHelper.GetKey() : _factoryKey; 
    }   
} 

Теперь я могу заменить [Сделка] S # Arp атрибуте с вновь созданной [FederationTransaction] следующим образом:

[HttpGet] 
[FederationTransaction] 
public ActionResult Index() 
{ 
    var viewModel = NHibernateSession.Current.QueryOver<SomeDemoModel>().List() 
    return View(viewModel);    
} 

Ни кода внутри контроллера не должен знать, что его использование Федерация Sql Azure. Все должно работать.

Любые мысли? Кто-нибудь нашел лучшее решение? Поделись, пожалуйста.

Смежные вопросы