EF Code First #12
نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۲/۲۶ ۱۰:۵۸:۰۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using System.Collections.Generic;
namespace EF_Sample07.DomainClasses { public class Category { public int Id { get; set; } public virtual string Name { get; set; } public virtual string Title { get; set; } public virtual ICollection<Product> Products { get; set; } } }
using System.ComponentModel.DataAnnotations;
namespace EF_Sample07.DomainClasses { public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; }
[ForeignKey("CategoryId")] public virtual Category Category { get; set; } public int CategoryId { get; set; } } }
using System.Data.Entity; using System;
namespace EF_Sample07.DataLayer.Context { public interface IUnitOfWork { IDbSet<TEntity> Set<TEntity>() where TEntity : class; int SaveChanges(); } }
using System.Data.Entity; using EF_Sample07.DomainClasses;
namespace EF_Sample07.DataLayer.Context { public class Sample07Context : DbContext, IUnitOfWork { public DbSet<Category> Categories { set; get; } public DbSet<Product> Products { set; get; }
#region IUnitOfWork Members public new IDbSet<TEntity> Set<TEntity>() where TEntity : class { return base.Set<TEntity>(); } #endregion } }
uow.Set<Product>
using EF_Sample07.DomainClasses; using System.Collections.Generic;
namespace EF_Sample07.ServiceLayer { public interface ICategoryService { void AddNewCategory(Category category); IList<Category> GetAllCategories(); } }
using EF_Sample07.DomainClasses; using System.Collections.Generic;
namespace EF_Sample07.ServiceLayer { public interface IProductService { void AddNewProduct(Product product); IList<Product> GetAllProducts(); } }
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses;
namespace EF_Sample07.ServiceLayer { public class EfCategoryService : ICategoryService { IUnitOfWork _uow; IDbSet<Category> _categories; public EfCategoryService(IUnitOfWork uow) { _uow = uow; _categories = _uow.Set<Category>(); }
public void AddNewCategory(Category category) { _categories.Add(category); }
public IList<Category> GetAllCategories() { return _categories.ToList(); } } }
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses;
namespace EF_Sample07.ServiceLayer { public class EfProductService : IProductService { IUnitOfWork _uow; IDbSet<Product> _products; public EfProductService(IUnitOfWork uow) { _uow = uow; _products = _uow.Set<Product>(); }
public void AddNewProduct(Product product) { _products.Add(product); }
public IList<Product> GetAllProducts() { return _products.Include(x => x.Category).ToList(); } } }
using System.Collections.Generic; using System.Data.Entity; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07 { class Program { static void Main(string[] args) { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>());
HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().CacheBy(InstanceScope.Hybrid).Use<Sample07Context>(); x.For<ICategoryService>().Use<EfCategoryService>(); });
var uow = ObjectFactory.GetInstance<IUnitOfWork>(); var categoryService = ObjectFactory.GetInstance<ICategoryService>();
var product1 = new Product { Name = "P100", Price = 100 }; var product2 = new Product { Name = "P200", Price = 200 }; var category1 = new Category { Name = "Cat100", Title = "Title100", Products = new List<Product> { product1, product2 } }; categoryService.AddNewCategory(category1); uow.SaveChanges(); } } }
public enum InstanceScope
{
PerRequest = 0,
Singleton = 1,
ThreadLocal = 2,
HttpContext = 3,
Hybrid = 4,
HttpSession = 5,
HybridHttpSession = 6,
Unique = 7,
Transient = 8,
} using System.Web.Mvc; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer; using EF_Sample07.DataLayer.Context; using System.Collections.Generic;
namespace EF_Sample07.MvcAppSample.Controllers { public class HomeController : Controller { IProductService _productService; ICategoryService _categoryService; IUnitOfWork _uow; public HomeController(IUnitOfWork uow, IProductService productService, ICategoryService categoryService) { _productService = productService; _categoryService = categoryService; _uow = uow; }
[HttpGet] public ActionResult Index() { var list = _productService.GetAllProducts(); return View(list); }
[HttpGet] public ActionResult Create() { ViewBag.CategoriesList = new SelectList(_categoryService.GetAllCategories(), "Id", "Name"); return View(); }
[HttpPost] public ActionResult Create(Product product) { if (this.ModelState.IsValid) { _productService.AddNewProduct(product); _uow.SaveChanges(); }
return RedirectToAction("Index"); }
[HttpGet] public ActionResult CreateCategory() { return View(); }
[HttpPost] public ActionResult CreateCategory(Category category) { if (this.ModelState.IsValid) { _categoryService.AddNewCategory(category); _uow.SaveChanges(); }
return RedirectToAction("Index"); } } }
using System; using System.Data.Entity; using System.Web.Mvc; using System.Web.Routing; using EF_Sample07.DataLayer.Context; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07.MvcAppSample
{ // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); }
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); }
protected void Application_Start() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>()); HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); initStructureMap(); }
private static void initStructureMap() { ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context()); x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>(); x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>(); });
//Set current Controller factory as StructureMapControllerFactory ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); }
protected void Application_EndRequest(object sender, EventArgs e) { ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects(); } }
public class StructureMapControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return ObjectFactory.GetInstance(controllerType) as Controller; } } }
using System; using System.Data.Entity; using EF_Sample07.DataLayer.Context; using EF_Sample07.ServiceLayer; using StructureMap;
namespace EF_Sample07.WebFormsAppSample { public class Global : System.Web.HttpApplication { private static void initStructureMap() { ObjectFactory.Initialize(x => { x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context()); x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>(); x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
x.SetAllProperties(y=> { y.OfType<IUnitOfWork>(); y.OfType<ICategoryService>(); y.OfType<IProductService>(); }); }); }
void Application_Start(object sender, EventArgs e) { Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>()); HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize(); initStructureMap(); }
void Application_EndRequest(object sender, EventArgs e) { ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects(); }
using System.Web.UI; using StructureMap;
namespace EF_Sample07.WebFormsAppSample { public class BasePage : Page { public BasePage() { ObjectFactory.BuildUp(this); } } }
using System; using EF_Sample07.DataLayer.Context; using EF_Sample07.DomainClasses; using EF_Sample07.ServiceLayer;
namespace EF_Sample07.WebFormsAppSample { public partial class AddProduct : BasePage { public IUnitOfWork UoW { set; get; } public IProductService ProductService { set; get; } public ICategoryService CategoryService { set; get; }
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { bindToCategories(); } }
private void bindToCategories() { ddlCategories.DataTextField = "Name"; ddlCategories.DataValueField = "Id"; ddlCategories.DataSource = CategoryService.GetAllCategories(); ddlCategories.DataBind(); }
protected void btnAdd_Click(object sender, EventArgs e) { var product = new Product { Name = txtName.Text, Price = int.Parse(txtPrice.Text), CategoryId = int.Parse(ddlCategories.SelectedItem.Value) }; ProductService.AddNewProduct(product); UoW.SaveChanges(); Response.Redirect("~/Default.aspx"); } } }
_uow.SaveChanges();
public class MyDbContextBase : DbContext, IUnitOfWork
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class CompareAttribute : ValidationAttribute
{
public CompareAttribute(string originalProperty, string confirmProperty)
{
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty
{
get;
private set;
}
public string OriginalProperty
{
get;
private set;
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
return String.Equals(((User)value).Password, ((User)value).RepeatPassword);
}
}
//[CompareAttribute("Password", "RepeatPassword", ErrorMessage = "Not Compare!")]
public class User
{
public Int64 UserId { get; set; }
[Required(ErrorMessageResourceName = "Password", ErrorMessageResourceType = typeof(ErrorMessageResource))]
public String Password { get; set; }
[NotMapped]
[Required(ErrorMessageResourceName = "RepeatPassword", ErrorMessageResourceType = typeof(ErrorMessageResource))]
//[CompareAttribute("Password","RepeatPassword" , ErrorMessage = "Not Compare!")]
public String RepeatPassword { get; set; }
}
using System;
using System.ComponentModel.DataAnnotations;
namespace Test
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class CompareAttribute : ValidationAttribute
{
public CompareAttribute(string originalProperty, string confirmProperty)
{
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty { get; private set; }
public string OriginalProperty { get; private set; }
protected override ValidationResult IsValid(object value, ValidationContext ctx)
{
if (value == null)
return new ValidationResult("لطفا فیلدها را تکمیل نمائید");
var confirmProperty = ctx.ObjectType.GetProperty(ConfirmProperty);
if (confirmProperty == null)
throw new InvalidOperationException(string.Format("لطفا فیلد {0} را تعریف نمائید", ConfirmProperty));
var confirmValue = confirmProperty.GetValue(ctx.ObjectInstance, null) as string;
if (string.IsNullOrWhiteSpace(confirmValue))
return new ValidationResult(string.Format("لطفا فیلد {0} را تکمیل نمائید", ConfirmProperty));
var originalProperty = ctx.ObjectType.GetProperty(OriginalProperty);
if (originalProperty == null)
throw new InvalidOperationException(string.Format("لطفا فیلد {0} را تعریف نمائید", OriginalProperty));
var originalValue = originalProperty.GetValue(ctx.ObjectInstance, null) as string;
if (string.IsNullOrWhiteSpace(originalValue))
return new ValidationResult(string.Format("لطفا فیلد {0} را تکمیل نمائید", OriginalProperty));
return originalValue == confirmValue ? ValidationResult.Success : new ValidationResult("مقادیر وارد شده یکسان نیستند");
}
}
}
سلام و خسته نباشید استاد نصیری
سوال بنده اینه که استفاده از لایه سرویس ضرورتی داره ؟ مشکلی پیش میاد اگه این لایه رو به طور کامل خذف کنیم و مستقیم با UnitOfWork کار کنیم؟
چون با استفاده از این لایه به ازای یک عمل مانند ذخیره کردن یک شی در پایگاه داده باید 2 شی (یکی از لایه مدل و دیگری از لایه سرویس) تعریف بشه ضمن آنکه وفتی تعداد کلاسها زیاد بشه متد initStructureMap() پیچیده میشه
تشکر فراوان
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context());
x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>();
x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
});
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
protected void Application_BeginRequest
public void Init(HttpApplication context)
{
context.BeginRequest += beginRequest;
}
void Application_Start(object sender, EventArgs e)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>());
public class MyContext : DbContext, IUnitOfWork
Return Base.SaveChanges();
try
{
applyCorrectYeKe();
auditFields();
//and another methods ...
Return base.SaveChanges();
}
catch (DbEntityValidationException validationException)
{
//...
}
catch (DbUpdateConcurrencyException concurrencyException)
{
//...
}
catch (DbUpdateException updateException)
{
//...
}
public int SaveChanges(string userName, bool updateAuditFields = true)
Public Function SaveChanges() As Integer Implements IUnitOfWork.SaveChanges
Try
ApplyCorrectYeKe()
'auditFields()
Return MyBase.SaveChanges()
Catch validationException As DbEntityValidationException
'...
Catch concurrencyException As DbUpdateConcurrencyException
'...
Catch updateException As DbUpdateException
'...
End Try
End Function
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
_uow.Set<Person>().Local
db.Entry(post).State = EntityState.Modified;
public interface IUnitOfWork
{
//...
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
}
در این مثالها فقط از اینترفیسهای ServiceLayer (و نه DataLayer مجزای آن) به کمک ترزیق وابستگیها در لایه نمایشی استفاده شده.اما چرا (مثلا) در پروژه Console EF_Sample07 (یا همون لایه نمایشی UI) رفرنسی به DataLayer زده شده و از UOW که اینترفیسی در لایه DL هست استفاده شده؟ ایا اینکار یکسری قراردادها رو نقض نمیکنه؟ +
using EF_Sample07.DataLayer.Context;
_uow.SaveChanges();
//...
uow.SaveChanges();
//...
var product3 = new Product { Name = "P300", Price = 300 };
var category2 = new Category
{
Name = "Cat200",
Title = "Title200",
Products = new List<Product> { product3 }
};
categoryService.AddNewCategory(category2);
uow.SaveChanges();
public interface IGenericService<T>: IDisposable where
T : class
public static class DataFactory
{
public static IUnitOfWork UnitOfWork
{
get { return ObjectFactory.GetInstance<IUnitOfWork>(); }
}
public static ICategoryService CategoryService
{
get { return ObjectFactory.GetInstance<IUnitOfWork>(); }
}
public static IProductService ProductService
{
get { return ObjectFactory.GetInstance<IUnitOfWork>(); }
}
}
...
public HomeController()
{
_productService = DataFactory.ProductService;
_categoryService = DataFactory.CategoryService;
_uow = DataFactory.UnitOfWork;
}
ObjectFactory.GetInstance<IProductService>()
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return ObjectFactory.GetInstance(controllerType) as Controller;
}
} routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
throw new InvalidOperationException(string.Format("Page not found: {0}", requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}سلام
با توجه به گفته دوستمون (بنابر این باید برای هر ماژول dll ای تولید کرد که حاوی DomainClassها , ServiceLayerها ، Controllerها و DbContext مربوط به اون ماژول باشه)
اگر از این الگو برای طراحی نرم افزار استفاده شود خوب برای ارتباط بین ماژولها که باید رفرنس همدیگر را در خود درج نمایند و در این صورت با circular dependency روبه رو میشویم
برای جلوگیری ای این خطا چه راه حلی پیشنهاد میدهید؟
public IList<BlogPost> GetLatestBlogPosts(int pageNumber, int recordsPerPage = 4)
{
var skipRecords = pageNumber * recordsPerPage;
return _blogPosts
.OrderByDescending(x => x.Id)
.Skip(skipRecords)
.Take(recordsPerPage)
.ToList();
}public partial class MyCtx1 : DbContext
{
public MyCtx1(string connectionString) : base(connectionString) { }
} x.For<IUnitOfWork>().HttpContextScoped().Use(() =>
{
var ctx = new Sample07Context();
ctx.Database.Connection.ConnectionString = "...";
return ctx;
});public static void ChangeDatabase(string name)
{
var sqlConnectionStringBuilder =
new SqlConnectionStringBuilder(ConfigHelper.ActiveConnection);
sqlConnectionStringBuilder["Database"] = name
ConfigHelper.ActiveConnection = sqlConnectionStringBuilder.ToString();
Database.DefaultConnectionFactory =
new System.Data.Entity.Infrastructure.SqlConnectionFactory(ConfigHelper.ActiveConnectionString());
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<TestContext, MigrationConfiguration>());
using (var context = new TestContext())
{
context.Database.Initialize(true);
}
}<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetAllProducts" TypeName="ServiceLayer.EfProductService">
</asp:ObjectDataSource>با سلام
"در پاسخ یکی از سوالهافرمودید با استفاده از IUnitOfWork اگر متد جاری شما از 10 کلاس هم استفاده کند، تماما با یک وهله از Context کار میکنند"
موقعی که از context یک وهله میگیریم و از Using استفاده میکنیم آیا به ازا هر کلاسی که در این scope هست connection جدیدی استفاده میشه ؟
آیا هنگام استفاده از Using موارد مربوط به همزمانی و transaction مدیریت نمیشه ؟
اگر این طور نیست مزیت روش بالا نسبت به استفاده از Using چیست ؟
ممنون
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
void Update<TEntity>(TEntity entity) where TEntity : class;
}
public class MyContext : DbContext, IUnitOfWork
{
public void Update<TEntity>(TEntity entity) where TEntity : class
{
var fqen = GetEntityName<TEntity>();
object originalItem;
EntityKey key = (IObjectContextAdapter)this).ObjectContext.CreateEntityKey
(fqen, entity);
if (((IObjectContextAdapter)this).ObjectContext.TryGetObjectByKey(key, out
originalItem))
{
((IObjectContextAdapter)this).ObjectContext.ApplyCurrentValues
(key.EntitySetName, entity);
}
((IObjectContextAdapter)this).ObjectContext.ApplyCurrentValues
(key.EntitySetName, entity);
}
private string GetEntityName<TEntity>() where TEntity : class
{
return string.Format("{0}.{1}", ((IObjectContextAdapter)this).ObjectContext.
DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}
#region IUnitOfWork Members
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
#endregion
}[MetadataType(typeof(CustomerMetadata))]
public partial class Customer
{
class CustomerMetadata
{
}
}
public partial class Customer : IValidatableObject
{namespace Service.Interfaces
{
public interface IGenericService<T>
{
void AddOrUpdate(T entity);
void Delete(T entity);
T Find(Func<T, bool> predicate);
T GetLast(Func<T, bool> predicate);
IList<T> GetAll();
IList<T> GetAll(Func<T, bool> predicate);
IList<T> GetAll(Expression<Func<T, object>> orderby);
IList<T> GetAll(Func<T, bool> predicate, Expression<Func<T, object>> orderby);
Task<List<T>> GetAllAsync();
Task<List<T>> GetAllAsync(Func<T, bool> predicate);
Task<List<T>> GetAllAsync(Expression<Func<T, object>> orderby);
Task<List<T>> GetAllAsync(Func<T, bool> predicate, Expression<Func<T, object>> orderby);
int Count();
int Count(Func<T, bool> predicate);
}
}public interface IBookGroupService:IGenericService<BookGroup>
{
}public class EFGenericService<TEntity> : IGenericService<TEntity>
where TEntity : class
{
protected IUnitOfWork _uow;
protected IDbSet<TEntity> _tEntities;
public EFGenericService(IUnitOfWork uow)
{
_uow = uow;
_tEntities = _uow.Set<TEntity>();
}
public void AddOrUpdate(TEntity entity)
{
_tEntities.AddOrUpdate(entity);
}
public virtual void Delete(TEntity entity)
{
_tEntities.Remove(entity);
}
public virtual TEntity Find(Func<TEntity, bool> predicate)
{
return _tEntities.Where(predicate).FirstOrDefault();
}
public virtual TEntity GetLast(Func<TEntity, bool> predicate)
{
return _tEntities.Where(predicate).Last();
}
public virtual IList<TEntity> GetAll()
{
return _tEntities.ToList();
}
public virtual IList<TEntity> GetAll(Func<TEntity, bool> predicate)
{
return _tEntities.Where(predicate).ToList();
}
public virtual IList<TEntity> GetAll(Expression<Func<TEntity, object>> @orderby)
{
return _tEntities.OrderBy(@orderby).ToList();
}
public virtual IList<TEntity> GetAll(Func<TEntity, bool> predicate, Expression<Func<TEntity, object>> @orderby)
{
return _tEntities.OrderBy(@orderby).Where(predicate).ToList();
}
public async Task<List<TEntity>> GetAllAsync()
{
return await Task.Run(() => _tEntities.ToList());
}
public async Task<List<TEntity>> GetAllAsync(Func<TEntity, bool> predicate)
{
return await Task.Run(() => _tEntities.Where(predicate).ToList());
}
public async Task<List<TEntity>> GetAllAsync(Expression<Func<TEntity, object>> @orderby)
{
return await Task.Run(() => _tEntities.OrderBy(@orderby).ToList());
}
public async Task<List<TEntity>> GetAllAsync(Func<TEntity, bool> predicate, Expression<Func<TEntity, object>> @orderby)
{
return await Task.Run(()=> _tEntities.OrderBy(@orderby).Where(predicate).ToList());
}
public virtual int Count()
{
return _tEntities.Count();
}
public virtual int Count(Func<TEntity, bool> predicate)
{
return _tEntities.Count(predicate);
}
}public class EFBorrowService:EFGenericService<Borrow>,IBorrowService
{
public EFBorrowService(IUnitOfWork uow) : base(uow)
{
}
}public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new InvalidOperationException(string.Format("Page not found: {0}", requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
}
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily MyProject.Controllers.HomeController, MyProject.Controllers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullبا سلام و خسته نباشید
آقای نصیری با توجه به توضیحات شما اگه نیاز به متدهای (مثلا: where, Skip,take,...) داشته باشیم آیا این متدها رو هم باید پیاده سازی کنیم؟
یا اینکه لیستی از مقادیر موجود رو بخونیم و بعد با استفاده از linq کوری مورد نظر رو استخراج کنیم!؟
private static readonly ICatHotellService _catHotellService;
private static readonly ICatTourismService _catTourismService;
private static readonly ICatTourService _catTourService;
private static readonly IUnitOfWork _uow;
public DropDownList(ICatHotellService CatHotellService, IUnitOfWork ouw, ICatTourService CatTourService, ICatTourismService CatTourismService)
{
_uow=ouw;
_catHotellService = CatHotellService;
_catTourismService = CatTourismService;
_catTourService = CatTourService;
}public class MyBaseController : Controller
{
/// <summary>
/// from http://forums.asp.net/t/1776480.aspx/1?ExecuteCore+in+base+class+not+fired+in+MVC+4+beta
/// </summary>
protected override bool DisableAsyncSupport
{
get { return true; }
}
protected override void ExecuteCore()
{
base.ExecuteCore();
}
}using (var context = new MyContext())
{
context.Database.SqlQuery......
}با خوندن مطالب فوق این طور بر میاد که در Ef یک Context به صورت Singleton ایجاد بشه تا هم بهینه باشه و هم مباحث مدیریت Transactionها و غیره به راحتی مدیریت بشه.
اما در اینجا StackOverflow در این خصوص خوندم که بهتره برای هر thread یک Context مجزا ایجاد کرد و سیستم Pools کانکشن تکراری و ارتباط متعدد را چک میکند.
بنده اشتباه برداشت کردم و یا سیستم Pool استفاده دیگره ای دارد .
public void ChangeState<T>(T entity, EntityState state) where T : class
{
Entry<T>(entity).State = state;
} DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
public interface IUnitOfWork
{
//...
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
} namespace EF_Sample07.DataLayer.Context
{
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveAllChanges();
void MarkAsChanged<TEntity>(TEntity entity) where TEntity : class;
}
}
namespace EF_Sample07.DataLayer.Context
{
public class Sample07Context : DbContext, IUnitOfWork
{
public DbSet<Category> Categories { set; get; }
public DbSet<Product> Products { set; get; }
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
public int SaveAllChanges()
{
return base.SaveChanges();
}
public void MarkAsChanged<TEntity>(TEntity entity) where TEntity : class
{
base.Entry<TEntity>(entity).State = EntityState.Modified;
}
}
} context.Database.SqlQuery(type, sql, parameters)
public class MyContext : DbContext, IUnitOfWork
{
// ...
public IList<T> GetRows<T>(string sql, params object[] parameters) where T: class
{
return this.Database.SqlQuery<T>(sql, parameters).ToList();
}
}
آیا امکان این وجود دارد که کاربر یک سفارش را بصورت زیر ویرایش کند:
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context());
x.ForRequestedType<ICategoryService>().TheDefaultIsConcreteType<EfCategoryService>();
x.ForRequestedType<IProductService>().TheDefaultIsConcreteType<EfProductService>();
});
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
} x.For<IUnitOfWork>().CacheBy(InstanceScope.Hybrid).Use<Context>();
Warning 1 '....CacheBy(StructureMap.InstanceScope)' is obsolete:
x.For<IUsersService>().HybridHttpOrThreadLocalScoped().Use<UsersService>();
IDbSet<TEntity> Set<TEntity>() where TEntity : class; int SaveChanges();
public class Sample07Context : DbContext, IUnitOfWork
//search for person with ID = 1 in year 92.
using (var context = new TestContextNew())
{
// در اینجا هم باید بنحوی بتوان با مشخص کردن سال مورد نظر اطلاعات از جدول مربوطه لود شود
//Info_92 مثلا برای سال 92 از جدول
var result = from h in context.Info_News where h.ID == 1 select h;
dataGridView1.DataSource = result.ToList();
} context.Database.Connection.ConnectionString = "...";
private static void initStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.For<IPhoneTypeService>().Use<EFPhoneTypeService>();
x.Policies.SetAllProperties(y =>
{
y.OfType<IPhoneTypeService>();
});
});
//Set current Controller factory as StructureMapControllerFactory
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
protected void Application_EndRequest(object sender, EventArgs e)
{
HttpContextLifecycle.DisposeAndClearAll ();
}
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return ObjectFactory.GetInstance(controllerType) as Controller;
}
} StructureMap Exception Code: 202 No Default Instance defined for PluginFamily Iris.Datalayer.Context.IUnitOfWork, baran.Datalayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Database.SetInitializer<LoanContext>(null);
// تنظیمات اولیه برنامه که فقط یکبار باید در طول عمر برنامه انجام شود
ObjectFactory.Initialize(x =>
{
x.For<IUnitOfWork>().Use<LoanContext>();
x.For<IEmployeeService>().Use<EmployeeService>();
});
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
}
} public partial class frmMain : Form
{
private IContainer _container;
private IUnitOfWork _uow;
public frmMain()
{
InitializeComponent();
_container = ObjectFactory.Container.GetNestedContainer();
_uow = _container.GetInstance<IUnitOfWork>();
}
private void btnHomeLoanRequest_Click(object sender, System.EventArgs e)
{
var employeeService = _container.GetInstance<IEmployeeService>();
.
.
.
_uow.SaveChanges();
}
private void btnEditLoan_Click(object sender, System.EventArgs e)
{
var categoryService = container.GetInstance<ICategoryService>();
.
.
.
_uow.SaveChanges();
} Program.cs: Application.Run(ObjectFactory.GetInstance<frmMain>());
frmMain:
private IContainer _container;
private IUnitOfWork _uow;
public frmMain(IUnitOfWork uow, IContainer container)
{
InitializeComponent();
_container = container;
_uow = uow;
} private void btnHomeLoanRequest_Click(object sender, System.EventArgs e)
{
using (var container = ObjectFactory.Container.GetNestedContainer()) // کانتکست را به صورت خودکار دیسپوز میکند
{
var uow = container.GetInstance<IUnitOfWork>();
var employeeService = container.GetInstance<IEmployeeService>(); public class MyContext : DbContext
{
protected override void Dispose(bool disposing)
{
Debug.WriteLine("MyContext Dispose() is called.");
base.Dispose(disposing);
}
} public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
ObjectFactory.Initialize(x =>
{
x.For<Entities>().HttpContextScoped().Use(() => new Entities());
}); //------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace EFDbFirstDependencyInjection.DataLayer
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class TestDbIdentityEntities : DbContext
{
public TestDbIdentityEntities()
: base("name=TestDbIdentityEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Product> Products { get; set; }
}
}
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
interface IPostService
{
void AddPost(Post post);
IList<Post> GetPosts();
Post GetPost(int PostId);
int RemovePost(Post post);
int UpdatePost(Post post);
} public class PostService<T>:IPostService where T:Post
{
private readonly IUnitOfWork _uow;
private readonly IDbSet<T> _post;
public PostService(IUnitOfWork uow)
{
_uow = uow;
_post = _uow.Set<T>();
}
public void AddPost(T post)
{}
public IList<T> GetPosts()
{}
//...
{ DBContext GetGontext();
public DBContext GetGontext()
{
return new DBContext();
} public EditedMember Edit(Member member)
{
_context.Entry(member).State = EntityState.Modified;
}
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new Sample07Context
بعد از هر دستوری sp_reset_connection اجرا میشه. من فکر میکردم Context Per Request به معنای یک کانکشن باز در طول درخواست هست ولی ظاهرا اینطور نیست.
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null && requestContext.HttpContext.Request.Url != null)
return base.GetControllerInstance(requestContext, controllerType);
return ObjectFactory.GetInstance(controllerType) as Controller;
}
} ((DbSet<Product>)_products).RemoveRange()
var container = new Container(x => {
// تنظیمات در اینجا
}); public static class ObjectFactory
{
private static readonly Lazy<Container> _containerBuilder =
new Lazy<Container>(defaultContainer, LazyThreadSafetyMode.ExecutionAndPublication);
public static IContainer Container
{
get { return _containerBuilder.Value; }
}
private static Container defaultContainer()
{
return new Container(x =>
{
// تنظیمات در اینجا
});
}
} public partial class HomeController : Controller
{
private readonly IUnitOfWork _uow;
public HomeController(IUnitOfWork uow)
{
_uow = uow;
}
public virtual ActionResult Index()
{
return View();
}
}
public class TestController : Controller
{
private readonly IUnitOfWork _uow;
public TestController(IUnitOfWork uow)
{
_uow = uow;
}
public ActionResult GetData()
{
return Content("Data");
}
} @Html.Action("GetData", "Test") public interface IAsyncDbSet<T> : IDbSet<T> where T : class
{
Task<T> FindAsync(CancellationToken cancellationToken, params Object[] keyValues);
Task<T> FindAsync(params Object[] keyValues);
} return base.Set<TEntity>();
public class RoleService : IRoleService
{
private readonly IRoleRepository _repository;
public RoleService(IRoleRepository roleRepository)
{
_repository = roleRepository;
}
public ServiceResponse AddRole(RoleDtoModel roleDtoModel)
{
//Logic
var brokenRules = _validation.Reset()
.IsNullOrDefault(() => roleDtoModel.RoleName)
.Assert();
if (brokenRules.Any())
return ServiceResponse.Failed(brokenRules: brokenRules);
var role = _mapper.Map<Role>(roleDtoModel);
_repository.Save(role);
_repository.Commit();
return ServiceResponse.Successful();
}
}
public class RoleService : IRoleService
{
private readonly IUnitOfWork _uow;
private readonly DbSet<Role> _roles;
public RoleService(IUnitOfWork uow)
{
_uow = uow;
_roles = _uow.Set<Role>();
}
public async Task<ServiceResponse> AddRoleAysnc(RoleDtoModel roleDtoModel)
{
#region Validation Or Logic
var brokenRules = _validation.Reset()
.IsNullOrDefault(() => roleDtoModel.RoleName)
.Assert();
if (brokenRules.Any())
return ServiceResponse.Failed(brokenRules: brokenRules);
#endregion
await _roles.AddAsync(role);
await _uow.SaveChangesAsync();
return ServiceResponse.Successful();
}
}