سلام
من از EF6.4.4 Code First در پروژه ی .Net Framework 4.6.2 استفاده میکنم (Visual Studio 17.5.3) .
برای افزایش سرعت و محاسبه نکردن MappingView برای اولین باری که از دستورات EF در هر بار که برنامه اجرا میشه ، دیدم که از Catch کردن MappingView (مثلا در یک فایل) و بعد خوندن MappingView از اون منبع استفاده میکنند (حداقل یکی از راه های حل مشکل کندی برای اولین بار که دستورات EF در هر بار اجرای برنامه استفاده میشه ، اینه) .
در لینک زیر ، نحوه ی انجام این کار اومده :
https://learn.microsoft.com/en-us/ef...---ef6-onwards
در بخش "Generating Views" ، به درستی اطلاعات MappingView را درون فایل xml ذخیره کردم .
=========================
اما برای قضیه ی لود مشکل دارم (نه اینکه مشکل لود از فایل داشته باشم) . بلکه در همون مقاله گفت که برای لودش ، یک کلاسی بسازید که از کلاس DbMappingViewCache ارث بری کنه (این کلاس هم دو تا عضو abstract در کلاس پدر را که عضوهای MappingHashValue و GetView هستند را باید پیاده سازی کنه) .
بعد هم در انتهای اون مقاله گفت که برای اینکه EF از این کلاس استفاده کنه ، باید از attribute زیر استفاده کنیم :
[assembly: DbMappingViewCacheType(typeof(PhoneBookDbContext), typeof(PhoneBookDbMappingViewCache))]
PhoneBookDbContext ، نام کلاس مشتق DbContext و PhoneBookDbMappingViewCache هم نام کلاس مشتق DbMappingViewCache ام هست .
چون اولش assembly داره ، تا جایی که میدونم ، این نوع attribute ها ، برای یک کلاس یا عضو خاصی نیستند و برای اون assembly بکار برده میشوند (اسمبلی من ، پروژه و لایه ی DataAccess.dll هست) و توصیه میشه که این نوع attribute ها را درون فایل assemblyinfo.cs قرار بدیم (که این فایل درون پوشه ی Properties در اون اسمبلی قرار داره) .
یعنی استفاده از این کلاس ، توسط ما صورت نمیگیره و توسط EF بصورت اتوماتیک صورت میگیره .
کدهای کلاس PhoneBookDbMappingViewCache ام هم اینه :
using DataAccess.ExceptionModule;
using DataAccess.SerializationModule;
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure.MappingViews;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataAccess.EntityModule.Class.PreGeneratedView
{
internal class PhoneBookDbMappingViewCache : DbMappingViewCache
{
private DbMappingViewInfo dbMappingViewInfo;
public PhoneBookDbMappingViewCache()
{
this.dbMappingViewInfo = this.GetDbMappingViewInfo();
}
private DbMappingViewInfo GetDbMappingViewInfo()
{
string xmlFullFileName = "PreGeneratedMappingViews.xml";
string fullFilePath = AppDomain.CurrentDomain.BaseDirectory + xmlFullFileName;
if (File.Exists(fullFilePath) == false)
return null;
DbMappingViewInfo dbMappingViewInfo = XmlDataSerializer.ReadDataFromXmlFile<DbMappingVie wInfo>(xmlFullFileName);
return dbMappingViewInfo;
}
public override string MappingHashValue
{
get
{
return this.dbMappingViewInfo?.DbMappingHashValue;
}
}
public override DbMappingView GetView(EntitySetBase extent)
{
Debug.WriteLine("test\ntest\ntest");
if (extent == null)
throw new ArgumentNullException(nameof(extent), ExceptionMessage.argumentNullExceptionMessage);
EntityMappingViewInfoWrapper matchedEntityMappingViewInfoWrapper = this.dbMappingViewInfo?.EntityMappingViews?.Find(
(EntityMappingViewInfoWrapper currentEntityMappingView) =>
{
return currentEntityMappingView.EntityName == extent.Name;
});
if (matchedEntityMappingViewInfoWrapper == null || matchedEntityMappingViewInfoWrapper.EntitySql == null)
return null;
DbMappingView dbMappingView = new DbMappingView(matchedEntityMappingViewInfoWrapper. EntitySql);
return dbMappingView;
}
}
}
کد کلاس assemblyinfo.cs ام که فقط در خط اولش ، اون attribute را بهش اضافه کردم ، اینه :
using DataAccess.EntityModule.Class;
using DataAccess.EntityModule.Class.PreGeneratedView;
using System.Data.Entity.Infrastructure.MappingViews;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: DbMappingViewCacheType(typeof(PhoneBookDbContext), typeof(PhoneBookDbMappingViewCache))]
[assembly: AssemblyTitle("DataAccess")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DataAccess")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("53e7049a-2c36-46da-b435-1ef77baa5306")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
من هم این کار را کردم و در متد GetView در کلاس PhoneBookDbMappingViewCache ، هم breakpoint و هم دستور Debug.WriteLine نوشتم اما هیچ کدوم شون اجرا نشدن .
میدونید علت چیه و چه کار باید کرد که اعضای این کلاس توسط EF فراخوانی و استفاده بشن؟
==============
من مشکل شبیه این را در دو پست زیر دیدم (هر دو ، یک سئوال هستند) اما جواب خاصی ندیدم که بهش داده باشند :
Can't get DbMappingViewCache to cache my views · Issue #1695 · dotnet/ef6 (github.com)
و
C# - How to check if DbMappingViewCache caches the precompiled views - Stack Overflow
تشکر دوستان .