ایجاد یک DbContext مشترک بین entityهای پروژههای متفاوت
نویسنده: یونس بقائی
تاریخ: ۱۳۹۶/۰۲/۰۱ ۱۵:۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
در SampleProject1 مدل Product را داریم:
public partial class Product : Entity
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<byte> ProductTypeId { get; set; }
} public partial class ProductType : Entity
{
public byte Id { get; set; }
public string Name { get; set; }
} List<Assembly> allAssemblies = new List<Assembly>();
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (string dll in Directory.GetFiles(path, "*.Common.dll"))
allAssemblies.Add(Assembly.LoadFile(dll));
var type = typeof(Entity);
List<Type> types = allAssemblies
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p)).ToList();
List<string> entities = new List<string>();
foreach (var item in types)
{
entities.Add(item.Name);
}
types.Add(typeof(Entity)); public class ContextGenerator
{
public void Generate(List<string> entities, params Type[] types)
{
StringBuilder code = new StringBuilder();
code.AppendLine(@"
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using SampleProject1.Common.Models;
using SampleProject1.Common.Models.Mapping;
using SampleProject2.Common.Models;
using SampleProject2.Common.Models.Mapping;
namespace DbContextGenerator
{
public partial class TestContext : DbContext
{
static TestContext()
{
Database.SetInitializer<TestContext>(null);
}
public TestContext()
: base(""Data Source=.;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True"")
{
}
");
var pluralizeHelper = new PluralizeHelper();
foreach (var entity in entities)
{
code.AppendLine($@"public DbSet<{entity}> {pluralizeHelper.Pluralize(entity)} {{ get; set; }}");
}
code.AppendLine(@"protected override void OnModelCreating(DbModelBuilder modelBuilder)");
code.AppendLine(@"{");
foreach (var entity in entities)
{
code.AppendLine($@"modelBuilder.Configurations.Add(new {entity}Map());");
}
code.AppendLine(@"}");
code.AppendLine(@"}");
code.AppendLine(@"}");
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
parameters.ReferencedAssemblies.Add("System.Data.dll");
parameters.ReferencedAssemblies.Add("System.Data.Entity.dll");
parameters.ReferencedAssemblies.Add("System.ComponentModel.dll");
foreach (var type in types)
{
parameters.ReferencedAssemblies.Add(type.Assembly.Location);
}
parameters.ReferencedAssemblies.Add(typeof(DbSet).Assembly.Location);
parameters.ReferencedAssemblies.Add(typeof(DbContext).Assembly.Location);
parameters.ReferencedAssemblies.Add(typeof(IQueryable).Assembly.Location);
parameters.ReferencedAssemblies.Add(typeof(IQueryable<>).Assembly.Location);
parameters.ReferencedAssemblies.Add(typeof(System.ComponentModel.IListSource).Assembly.Location);
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = false;
parameters.OutputAssembly = "ProjectContext.dll";
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code.ToString());
if (results.Errors.HasErrors)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError error in results.Errors)
{
sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
}
throw new InvalidOperationException(sb.ToString());
}
}
} new ContextGenerator().Generate(entities, types.ToArray()); // generate dbContext
حال برای استفاده از Context تولید شده، به صورت زیر شیءایی را ساخته:
static DbContext _dbContext=null;
public static DbContext GetDbContextInstance()
{
if (_dbContext == null)
{
string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var dllversionAssm = Assembly.LoadFile(path + "\\ProjectContext.dll");
Type type = dllversionAssm.GetType("DbContextGenerator.TestContext");
_dbContext = (DbContext)Activator.CreateInstance(type);
}
return _dbContext;
} و سپس برای ساخت DbSet از هر Entity به کد زیر نیاز خواهیم داشت:
public static System.Data.Entity.DbSet<T> Get<T>() where T : class
{
var set = GetDbContextInstance().Set<T>();
return set;
} هم اکنون میتوان رکوردهای Entityها را واکشی کرده و یا آنها را با یکدیگر Join بزنیم:
var products = Get<Product>().ToList();
var productTypes = Get<ProductType>().ToList();
var query = from p in Get<Product>()
join pt in Get<ProductType>() on p.ProductTypeId equals pt.Id
select new
{
Id = p.Id,
Name = p.Name,
ProductType = pt.Name
};
var JoinResult = query.ToList(); و نتیجه واکشی ها
[ComponentServiceInterface]
public interface ISampleProject1Service
{
IQueryable<Product> FetchAllProducts();
}
اما بعد از Generate و اجرا به همان Performance کدهای Compile شده میرسیم
public class ClaimBasedAuthorzationAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase context)
{
// get the user info here [cache is prefered]
return
context.User.Identity is ClaimsIdentity
&& ((ClaimsIdentity)context.User.Identity).HasClaim(x =>
x.Type == "ClaimType" && x.Value.ToLower() == "something".ToLower());
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
}