我想寫一些東西,我可以傳入一個類(其中將包括新數據,包括主鍵值),並使用實體框架,使用主鍵檢索實體。所以,我有一個類,包括主鍵值,但我不一定知道主鍵(但實體框架)。通用實體框架更新器
(我以後還需要那麼一般更新實體,但是這是一個單獨的問題)
有一個簡單的方法在LINQ做到這一點?
我想寫一些東西,我可以傳入一個類(其中將包括新數據,包括主鍵值),並使用實體框架,使用主鍵檢索實體。所以,我有一個類,包括主鍵值,但我不一定知道主鍵(但實體框架)。通用實體框架更新器
(我以後還需要那麼一般更新實體,但是這是一個單獨的問題)
有一個簡單的方法在LINQ做到這一點?
據我所知,你有一個對象沒有被上下文跟蹤,你想用EF來查詢數據庫中的等價實體。 (然後您想用對象的值更新數據庫,但這將是一個單獨的問題。)
如果知道主鍵值,可以使用Find方法從數據庫中獲取實體。棘手的問題是以通用的方式獲取主鍵值。這是我們希望在EF的未來版本中變得更容易,但現在我已經制作了一些擴展方法來提供幫助。
首先,讓我們得到給定類型的主鍵名稱。這是棘手的問題。它需要下降到ObjectContext中,並使用MetadataWorkspace:
public static IEnumerable<string> PrimayKeysFor(
this DbContext context,
object entity)
{
Contract.Requires(context != null);
Contract.Requires(entity != null);
return context.PrimayKeysFor(entity.GetType());
}
public static IEnumerable<string> PrimayKeysFor(
this DbContext context,
Type entityType)
{
Contract.Requires(context != null);
Contract.Requires(entityType != null);
var metadataWorkspace =
((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
var objectItemCollection =
(ObjectItemCollection)metadataWorkspace.GetItemCollection(DataSpace.OSpace);
var ospaceTypes = metadataWorkspace.GetItems<EntityType>(DataSpace.OSpace);
var ospaceType = ospaceTypes
.FirstOrDefault(t => objectItemCollection.GetClrType(t) == entityType);
if (ospaceType == null)
{
throw new ArgumentException(
string.Format(
"The type '{0}' is not mapped as an entity type.",
entityType.Name),
"entityType");
}
return ospaceType.KeyMembers.Select(k => k.Name);
}
}
現在,我們可以添加一個擴展方法,它利用這點來獲取給定的實體鍵值(它沒有被跟蹤):
public static object[] PrimayKeyValuesFor(this DbContext context, object entity)
{
Contract.Requires(context != null);
Contract.Requires(entity != null);
var entry = context.Entry(entity);
return context.PrimayKeysFor(entity)
.Select(k => entry.Property(k).CurrentValue)
.ToArray();
}
一旦我們有了它,使用Find可以非常容易地在數據庫中獲取與給定對象相對應的實體,而無需瞭解對象的任何信息。例如:
var databaseOrderLine =
context.Set<OrderLine>().Find(context.PrimayKeyValuesFor(orderLine));
您可以使用一個通用的ContextHelper:
public class ContextHelper<T> : IContextHelper<T>
{
//Instantiate your own EntityFrameWork DB context here,
//Ive called the my EntityFramework Namespace 'EF' and the context is named 'Reporting'
private EF.DataContext DbContext = new EF.DataContext();
public bool Insert<T>(T row) where T : class
{
try
{
DbContext.Set<T>().Add(row);
DbContext.SaveChanges();
return true;
}
catch(Exception ex)
{
return false;
}
}
public bool Update<T>(T row) where T : class
{
try
{
DbContext.Set<T>().AddOrUpdate(row);
DbContext.SaveChanges();
return true;
}
catch (Exception ex)
{
return false;
}
}
public bool Delete<T>(T row) where T : class
{
return Update(row); //Pass an entity with IsActive = false and call update method
}
public bool AddRows<T>(T[] rows) where T : class
{
try
{
DbContext.Set<T>().AddOrUpdate(rows);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
,並使用該稱呼它:
public void NewEmailRecipient(EF.EmailRecipient recipient)
{
// logic operation here
EntityToDB(recipient);
}
public void NewReportRecipient(EF.ReportRecipient recipient)
{
// logic operation here
EntityToDB(recipient);
}
public void UpdateEmailRecipient(EF.EmailRecipient recipient)
{
// logic operation here
UpdateEntity(recipient);
}
public void UpdateReportRecipient(EF.ReportRecipient recipient)
{
// logic operation here
UpdateEntity(recipient);
}
// call generic methods to update DB
private void EntityToDB<T>(T entity) where T : class
{
var context = new ContextHelper<T>();
context.Insert(entity);
}
private void UpdateEntity<T>(T entity) where T : class
{
var context = new ContextHelper<T>();
context.Update(entity);
}
我已經張貼在這裏演示解決方案
https://github.com/andyf1ynn/EntityFramwork-Generic-Type-DAL