我正在尝试使用通用存储库实现分页和排序.如何在DbSet中按列的默认顺序获取主键列?
DbSet = Context.Set<T>();
public IQueryable<T> GetAll(int pageNumber = 0, int pageSize = 10, string sortColumn = "")
{
return DbSet.OrderBy("how to use primary key column here").Skip(pageNumber * pageSize)Take(pageSize);
}
Run Code Online (Sandbox Code Playgroud) 我需要模仿EF的DbContext.我在这里使用这种方法,效果很好.
// mock a DbSet
var mockDbSet = Substitute.For<DbSet<Foo>, IQueryable<Foo>>();
var data = new List<Foo>().AsQueryable();
((IQueryable<Foo>)mockDbSet).Provider.Returns(data.Provider);
((IQueryable<Foo>)mockDbSet).Expression.Returns(data.Expression);
((IQueryable<Foo>)mockDbSet).ElementType.Returns(data.ElementType);
((IQueryable<Foo>)mockDbSet).GetEnumerator().Returns(data.GetEnumerator());
// now add it to a mock DbContext
var mockContext = Substitute.For<MyDbContextClass>();
mockContext.Set<Foo>().Returns(mockDbSet);
Run Code Online (Sandbox Code Playgroud)
然而,在某些测试中,我需要能够调用mockContext.Set<Foo>().Add(someFoo)和mockContext.Set<Foo>().Remove(otherFoo),并为潜在的添加/删除逻辑工作.
我试过这个:
mockDbSet.When(x => x.Add(Arg.Any<Foo>())).Do(x => data.Add(x.Arg<Foo>()));
Run Code Online (Sandbox Code Playgroud)
但它抛出了 Collection was modified; enumeration operation may not execute.
那么如何实现添加/删除功能呢?
我不确定这是否可行,但我正在尝试对使用DbSet的存储库进行单元测试.我认为最简单的解决方案就是制作一个Enumerable,然后用它替换DbSet,这是我的尝试.
我正在使用C#,EntityFramework,XUnit和Moq
[Fact]
public void SomeTest()
{
//arrange
var mockContext = new Mock<MyDbContext>();
var mockData = new List<Person>
{
new Person { Name = "Jim", Age = 47 }
};
mockContext.Setup(db => db.Persons).Returns((DbSet<Person>)mockData.AsQueryable());
var repo = PersonRepository(mockContext.Object);
//act
var result = repo.GetByFirstName("Jim");
//assert
//do some assertion
}
Run Code Online (Sandbox Code Playgroud)
抛出的错误是它无法将类型EnumerableQuery转换为mockContext.Returns语句中的DbSet.
这与接口的外观类似.
PersonRepository.cs
public class PersonRepository: EFRepository<Person>, IPersonRepository
{
public PersonRepository(DbContext dbContext) : base(dbContext)
{
}
public IQueryable<Link> GetByFirstName(string name)
{
return DbSet.Where(p => p.FirstName == name);
}
}
Run Code Online (Sandbox Code Playgroud)
IPersonRepository.cs
public interface IPersonRepository: …Run Code Online (Sandbox Code Playgroud) 我正在使用EF 5编写一个C#ASP.NET MVC 5 Web应用程序.使用EF映射我的数据库表会生成一个DbContext类和一个.edmx文件.今天,我正在阅读一篇关于创建泛型DAL类的好文章,但我停止了以下句子:
请注意,使用Entry方法更改实体的状态只会影响传递给方法的实际实体.与DbSet.Add方法不同,它不会级联图形并设置所有相关对象的状态.
这与这些问题中提到的内容相矛盾:
在上述所有问题的答案中,所有用户都提到使用System.Data.EntityState.Added与使用完全相同DbSet.Add.但我之前提到的文章首先指出,使用System.Data.EntityState.Added不会在图表中级联.
根据我的测试,我得出结论,使用System.Data.EntityState.Added将通过图表级联,与DBset.Add案例相同.这篇文章是错的,还是我的考试和问答?
我的Logs存储库中有以下两种方法.
public IEnumerable<Log> GetAll()
{
var db = new CasLogEntities();
return db.Logs;
}
public DbSet<Log> GetAllSet()
{
var db = new CasLogEntities();
return db.Logs;
}
Run Code Online (Sandbox Code Playgroud)
唯一的区别是一个返回一个IEnumerable的Log,另一个返回一个DbSet的Log.
在我的资产控制器中,我有以下代码
var allLogs = _logRepo.GetAllSet();
var Logs = (from log in allLogs
group log by log.DeviceId
into l
select new {DeviceId = l.Key, TimeStamp = l.Max(s => s.TimeStamp)}).ToList();
Run Code Online (Sandbox Code Playgroud)
现在问题是我在group by语句中获得了巨大的性能差异,这取决于我调用哪个repo方法.
任何人都可以解释一下.我当时认为在GetAll中将DbSet转换为IEnumerable导致Query执行,因此我在一个庞大的内存集中执行该组.而当GetAllSet将查询执行推迟到"ToList()"时,因此在服务器上通过工作来执行该组.
它是否正确?还有另一种解释方法吗?
我更喜欢让GetAll返回IEnumerable,因为我对它更熟悉并且它更容易进行测试.
版本信息:
我正在使用C#4.5,Entity Framework 6.0和MEF.
代码和单元测试
我创建了一个测试项目来解释这个问题:https: //skydrive.live.com/redir?resid = E3C97EC293A34048!2234
请打开UnitTest项目并尝试运行TestIfItWorks()单元测试.
问题
我想将非泛型DbSet转换为其通用版本,但我得到以下异常InvalidCastException: Cannot create a DbSet<IUser> from a non-generic DbSet for objects of type 'User':
var nonGeneric = context.Set(typeof(User));
var generic = nonGeneric.Cast<IUser>(); //Exception in here
Run Code Online (Sandbox Code Playgroud)
User类正在实现IUser,所以你会认为强制转换不应该是一个问题,除非DbSet代码仅限于具体的类(我希望不是我需要创建一个围绕非泛型DbSet的包装器将它转换为泛型DbSet或找到当前DbSet实现的替代方案).
如果您想知道我为什么使用接口,即使它们目前不受Microsoft支持,我会给您一些解释(希望这会过滤掉"不要那样做"而不是提供解决方案的响应):
我正在使用MEF和EntityFramework来创建一个松散耦合的数据层引擎,通过它我可以为每个项目提供实体(及其相应的配置).我一直在广泛使用Interfaces来定义引擎.使用MEF在运行时发现元数据和上下文中实体的具体实现.
摘自代码
[TestMethod]
public void TestIfItWorks()
{
//TODO: Please open the App.Config and change the PluginsPath to match the Plugins folder in your machine.
using (var dbContext = new MyContext()) //Please ignore this line for now. This was …Run Code Online (Sandbox Code Playgroud) 我们的编程涉及使用内存数据进行的一些Mock测试.因此,我们实现了以下代码,该代码首先创建Customer对象的内存数据
// Let us create some in-memory data
// Create a list of Customer
List<Customer> listOfCustomers = new List<BlahBlahExample.Domain.Objects.Customer>()
{ new Customer { CustomerID = "1 ",Orders = new HashSet<Order>(), CustomerDemographics = new HashSet<CustomerDemographic>(), CompanyName = "Chicago Bulls", ContactName = "Michael Jordan", ContactTitle = "top basket ball player", Address = "332 testing lane", City = "Chicago", Region = "Illinois", PostalCode = "484894", Country = "USA", Phone = "3293993", Fax = "39393" },
new Customer { CustomerID = "2 ",Orders = …Run Code Online (Sandbox Code Playgroud) 在MSDN文档之后,我们可以使用Local属性直接从上下文获取本地/缓存数据,而无需对数据源的其他请求:
获取一个ObservableCollection,它表示此集合中所有已添加,未更改和已修改实体的本地视图.
(...)
通过使用数据填充集合,此属性可用于数据绑定,例如,使用Load扩展方法,然后通过此属性绑定到本地数据.
问题是,代码不起作用(Local为空):
context.SampleEntities.Select(x => new { x.A, x.B }).Load();
// context.SampleEntities.Local.Count is 0
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,它似乎正常工作:
context.SampleEntities.Load();
// context.SampleEntities.Local.Count is not 0
Run Code Online (Sandbox Code Playgroud)
也许有人可以解释使用Local属性的正确方法是什么?
更重要的是,如何将它与部分加载的实体一起使用,如上面的情况?
string tableName = "TblStudents";
Dictionary<string, Type> myDictionary = new Dictionary<string, Type>()
{
{ "TblStudents", typeof(TblStudent) },
{ "TblTeachers", typeof(TblTeacher) }
};
// Context always same
DBContext dbContext = new DBContext();
DbSet dbSet = dbContext.Set(myDictionary[tableName]);
Run Code Online (Sandbox Code Playgroud)
上面的代码来自这篇文章,我可以DbSet动态地。我怎样才能在 Entity Framework Core 中做到这一点?
我在
DbSet dbSet = dbContext.Set(myDictionary[tableName]);
Run Code Online (Sandbox Code Playgroud)
Set新版本中似乎方法已更改。
帮助表示赞赏。
我正在尝试定义自己的DbSet,如:
public class MyDbSet<TEntity> : DbSet<TEntity>
where TEntity : class
{
public override TEntity Add(TEntity entity)
{
....
Run Code Online (Sandbox Code Playgroud)
并在DbContext中使用它
public MyDbSet<User> Users { get; set; }
Run Code Online (Sandbox Code Playgroud)
我面临的问题是Users在运行时将为null(因此无用)但我无法理解为什么.db.Users.Any(会抛出一些东西"value cannot be null"; 如果我替换和使用DbSet而不是
public DbSet<User> Users { get; set; }
Run Code Online (Sandbox Code Playgroud)
一切正常.
有谁知道我是否以及如何解决这个问题所以我可以使用自己的派生类?
编辑:
在收到一些评论之后,我澄清了为什么我这样做:我希望能够轻松地从数据检索机制切换到另一个而无需更改代码.例如,如果我决定在内存中进行缓存(缓存只是一个例子,我可能也想改变其他一些东西)我只是覆盖Any/Find/...in MyDbSet和读取字典而不是查询数据库,剩下的代码不变.这样,代码将执行"常规"操作,而无需考虑如何检索数据.因此,如果有人可以指出一种方法来做到这一点而不扩展DbSet也将回答问题的类.
非常感谢
dbset ×10
c# ×7
dbcontext ×2
unit-testing ×2
caching ×1
casting ×1
iqueryable ×1
local ×1
mef ×1
mocking ×1
moq ×1
nsubstitute ×1