понедельник, 3 ноября 2014 г.

MVC, EF, AppContext рабочий пример архитектуры

Описанная архитектура взята из проекта Expresscoin.

1-Контроллеры обращаются к отдельным сервисам AppContext-а:
this.AppContext.OrderService.GetUserOrders()

Базовый контроллер имеет ссылку на AppContext, который живет в web приложении
AppContext создается в базовом контроллере,
причем в конструкторе используется код для предотвращения создания нескольких экземпляров AppContext
protected BaseApiController()
        {
            this.AppContext = AppContext.Current;
            if (this.AppContext == null)
            {
                this.disposeAppContext = true;
                this.AppContext = AppContext.Current = new AppContext();
            }
        }

2-статическое свойство AppContext.Current сохраняет или достает экземпляр AppContext из/в
HttpContextFactory.Current.Items
public static AppContext Current
        {
            get { return (AppContext)HttpContextFactory.Current.Items[HttpContextKey]; }
            set { HttpContextFactory.Current.Items[HttpContextKey] = value; }
        }
т.о. в ситуации, когда в одном и том же запросе будет создаваться несколько контроллеров (хотя я не вижу как так может произойти на практике) один и тот же экземпляр будет браться из HttpContext.Items

3-HttpContextFactory инкапсулирует в себе доступ к HttpContext.Current, но при этом имеет возможность подсунутьфэйковый HttpContext для тестовых целей:
public static class HttpContextFactory
    {
        private static HttpContextBase _context;
        public static HttpContextBase Current
        {
            get
            {
                if (_context != null)
                    return _context;

                if (HttpContext.Current == null)
                    throw new InvalidOperationException("HttpContext not available");

                return new HttpContextWrapper(HttpContext.Current);
            }
        }

        public static void SetCurrentContext(HttpContextBase context)
        {
            _context = context;
        }
    }

4-AppContext выставляет наружу сервисы
public ICurrencyService CurrencyService { get { return this.service; } }
public IOrderService OrderService { get { return this.service; } }

Все эти сервисы реализует класс MainService
public AppContext()
        {
            this.service = new MainService();
        }

5-Класс MainService живет в business layer и представляет собой partial класс. Каждая отдельная часть реализует отдельный интерфейс: ICurrencyServic,  IOrderServic.

6- Внутри класса MainService есть ссылка на DbContext (здесь MainDB), который создается в конструкторе
        public MainService()
        {
            this.dbContext = new MainDB();
        }
7-Класс MainService наследует абстрактный класс Disposable (живет в Tools)
public abstract class Disposable : IDisposable
    {
        ~Disposable()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
        }
    }
это нужно для освобождения DbContex, в MainService:
protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.dbContext != null)
                {
                    this.dbContext.Dispose();
                    this.dbContext = null;
                }
            }
        }

В базовом контроллере, также реализуется Dispose:
protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.AppContext != null)
                {
                    if (this.disposeAppContext)
                    {
                        AppContext.Current = null;
                        this.AppContext.Dispose();
                    }
                    this.AppContext = null;
                }
            }
            base.Dispose(disposing);
        }

пятница, 1 августа 2014 г.

Совместная работа ASP Identity и EF Designer from database

Необходимо сделать следующие шаги:
1-получить sql код стандартных таблиц Identity (в SQL Management Studio) и с помощью этого кода создать такие же таблицы в своей базе.
2-изменить connection string используемый для Identity, в итоге в проекте будет иметь два connection string

 <add name="IdentityDbContext" connectionString="Data Source=BRESLAVSKY;Initial Catalog=MyNotesIdentity;Integrated Security=True" providerName="System.Data.SqlClient" />
  <add name="MyNotesIdentityEntities" connectionString="metadata=res://*/Entities.DataModel.csdl|res://*/Entities.DataModel.ssdl|res://*/Entities.DataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=BRESLAVSKY;initial catalog=MyNotesIdentity;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

3-если название connection sting Identity было изменено, то поменять его в конструкторе ApplicationDbContext.

Подробнее смотреть здесь.

среда, 30 июля 2014 г.

Контекст EntityFramework в MVC

Есть клас AppContext. У него в конструкторе создается экземпляр EntityContext.
Сам AppContext создается в конструкторе базового контреллера, и его экземпляр доступен
во всех контроллерах.

В AppContext реализуется работа с EF. Наружу выставляется интерфейс.

public class AppContext : IDataService
    {
        private static MyNotesEntities _entityContext;

        static AppContext()
        {
            _entityContext = new MyNotesEntities();
        }

        public void AddNote(Note note)
        {
            _entityContext.Notes.Add(note);
            _entityContext.SaveChanges();
        }

        public List<Note> GetNoteList()
        {
            return _entityContext.Notes.ToList();
        }
    }

public interface IDataService
    {
        void AddNote(Note note)
        List<Note> GetNoteList();
    }

 public class NoteController : Controller
    {
        AppContext _appContext;

       public NoteController()
        {
            _appContext = new AppContext();           
        }
}

Класс MyNotesEntities автоматически создается EF и наследует стандартный класс DbContext.