Lyu*_*rov 47 c# entity-framework-core
我正在尝试创建一个通用存储库来访问我的数据库.在EF6中我能够做到这一点,以获得一个特定的实体:
protected IDbSet<T> dbset;
public T Get(object id)
{
return this.dbset.Find(id);
}
Run Code Online (Sandbox Code Playgroud)
EF7中的DbSet缺少Find方法.有没有办法实现上面的代码?
bri*_*lam 23
这是一个非常粗略,不完整和未经测试.Find()的扩展方法实现.如果没有别的,它应该让你指向正确的方向.
真正的实现由#797跟踪.
static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues)
where TEntity : class
{
var context = ((IAccessor<IServiceProvider>)set).Service.GetService<DbContext>();
var entityType = context.Model.GetEntityType(typeof(TEntity));
var key = entityType.GetPrimaryKey();
var entries = context.ChangeTracker.Entries<TEntity>();
var i = 0;
foreach (var property in key.Properties)
{
var keyValue = keyValues[i];
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValue);
i++;
}
var entry = entries.FirstOrDefault();
if (entry != null)
{
// Return the local object if it exists.
return entry.Entity;
}
// TODO: Build the real LINQ Expression
// set.Where(x => x.Id == keyValues[0]);
var parameter = Expression.Parameter(typeof(TEntity), "x");
var query = set.Where((Expression<Func<TEntity, bool>>)
Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, "Id"),
Expression.Constant(keyValues[0])),
parameter));
// Look in the database
return query.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
小智 19
如果您使用的是EF 7.0.0-rc1-final,请在下面找到@bricelam在上一个答案中提供的代码的小更新.顺便说一句,非常感谢@bricelam - 你的代码对我非常有用.
这是我在"project.config"下的依赖项:
"dependencies": {
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta8",
"Microsoft.Framework.ConfigurationModel": "1.0.0-beta4",
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
"Microsoft.Framework.DependencyInjection": "1.0.0-beta8"
}
Run Code Online (Sandbox Code Playgroud)
以下是DbSet.Find(TEntity)的扩展方法:
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
using System;
using System.Linq;
using System.Linq.Expressions;
namespace Microsoft.Data.Entity.Extensions
{
public static class Extensions
{
public static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues) where TEntity : class
{
var context = ((IInfrastructure<IServiceProvider>)set).GetService<DbContext>();
var entityType = context.Model.FindEntityType(typeof(TEntity));
var key = entityType.FindPrimaryKey();
var entries = context.ChangeTracker.Entries<TEntity>();
var i = 0;
foreach (var property in key.Properties)
{
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[i]);
i++;
}
var entry = entries.FirstOrDefault();
if (entry != null)
{
// Return the local object if it exists.
return entry.Entity;
}
// TODO: Build the real LINQ Expression
// set.Where(x => x.Id == keyValues[0]);
var parameter = Expression.Parameter(typeof(TEntity), "x");
var query = set.Where((Expression<Func<TEntity, bool>>)
Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, "Id"),
Expression.Constant(keyValues[0])),
parameter));
// Look in the database
return query.FirstOrDefault();
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 9
由于声誉无法发表评论,但如果您使用RC2(或更高版本?)则应该使用
var context = set.GetService<ICurrentDbContext>().Context;
Run Code Online (Sandbox Code Playgroud)
代替
var context = set.GetService<DbContext>();
Run Code Online (Sandbox Code Playgroud)
我已经采取了一些以前提供的答案,并调整它们来解决一些问题:
密钥不应硬编码为"Id"
public static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues) where TEntity : class
{
var context = set.GetService<DbContext>();
var entityType = context.Model.FindEntityType(typeof(TEntity));
var key = entityType.FindPrimaryKey();
var entries = context.ChangeTracker.Entries<TEntity>();
var i = 0;
foreach (var property in key.Properties)
{
var i1 = i;
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[i1]);
i++;
}
var entry = entries.FirstOrDefault();
if (entry != null)
{
// Return the local object if it exists.
return entry.Entity;
}
var parameter = Expression.Parameter(typeof(TEntity), "x");
var query = set.AsQueryable();
i = 0;
foreach (var property in key.Properties)
{
var i1 = i;
query = query.Where((Expression<Func<TEntity, bool>>)
Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, property.Name),
Expression.Constant(keyValues[i1])),
parameter));
i++;
}
// Look in the database
return query.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)小智 5
所以...上面的查找方法效果很好,但是如果你的模型中没有名为"Id"的列,那么整个过程将在下一行失败.我不确定为什么OP会把硬编码的值放到这个位置
Expression.Property(parameter, "Id"),
Run Code Online (Sandbox Code Playgroud)
这是一个修订版,它将为那些正确命名我们的Id列的人修复它.:)
var keyCompare = key.Properties[0].Name;
// TODO: Build the real LINQ Expression
// set.Where(x => x.Id == keyValues[0]);
var parameter = Expression.Parameter(typeof(TEntity), "x");
var query = set.Where((Expression<Func<TEntity, bool>>)
Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, keyCompare),
//Expression.Property(parameter, "Id"),
Expression.Constant(keyValues[0])),
parameter));
// Look in the database
return query.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
如果你在实体对象上有多个Key设置并且你正在查找的键不是第一个,那么这个STILL很可能会失败,但是这样做应该有点笨拙.
没有足够的声誉来评论,但@ Roger-Santana在控制台app/seperate程序集中使用它时有一个错误:
var i = 0;
foreach (var property in key.Properties)
{
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[i]);
i++;
}
var entry = entries.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
在foreach中捕获'i'的值,这样当调用entries.FirstOrDefault()时,keyValues [i]的值为(至少)keyValues [i ++],在我的情况下崩溃时出现索引错误.修复方法是通过循环复制'i'的值:
var i = 0;
foreach (var property in key.Properties)
{
var idx =i;
entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[idx]);
i++;
}
var entry = entries.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16286 次 |
| 最近记录: |