我正在使用EF 4.3.1 ...刚刚升级到4.4(问题仍然存在),由EF 4.x DbContext Generator生成的数据库优先POCO实体.我有以下数据库名为'Wiki'(用于创建表和数据的SQL脚本在这里):

编辑Wiki文章时,不会更新其记录,而是将新版本作为新记录插入,并使修订计数器递增.在我的数据库中有一位作者"John Doe",它有两篇文章,"文章A"和"文章B",其中文章A有两个版本(1和2),但文章B只有一个版本.

我禁用了延迟加载和代理创建(这里是我使用LINQPad的示例解决方案).我想获得由名字以"John"开头的人创建的文章的最新版本,所以我做了以下查询:
Authors.Where(au => au.Name.StartsWith("John"))
.Select(au => au.Articles.GroupBy(ar => ar.Title)
.Select(g => g.OrderByDescending(ar => ar.Revision)
.FirstOrDefault()))
Run Code Online (Sandbox Code Playgroud)
这会产生错误的结果,并仅检索第一篇文章:

结交查询小的变化,通过更换.FirstOrDefault()与.Take(1)下面的查询结果:
Authors.Where(au => au.Name.StartsWith("John"))
.Select(au => au.Articles.GroupBy(ar => ar.Title)
.Select(g => g.OrderByDescending(ar => ar.Revision)
.Take(1)))
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,此查询产生了正确的结果(尽管有更多嵌套):

我假设EF生成略有不同的SQL查询,一个只返回单个文章的最新版本,另一个返回所有文章的最新版本.两个查询生成的丑陋SQL差别不大(比较:针对.FirstOrDefault()的SQL与针对.Take (1)的SQL相比,但它们都返回正确的结果:
.FirstOrDefault()

.Take(1) (重新排列列顺序以便于比较)

因此,罪魁祸首不是生成的SQL,而是EF对结果的解释.为什么EF将第一个结果解释为单个Article实例,而将第二个结果解释为两个Article实例?为什么第一个查询返回不正确的结果?
编辑:我已经打开了关于Connect 的错误报告.如果您认为解决此问题很重要,请进行投票.
public interface IDatabaseContext : IDisposable {
IDbSet<MyEntity1> Entities1 { get; set; }
}
public class MyDbContext : DbContext, IDatabaseContext {
IDbSet<MyEntity1> Entities1 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
由于此处描述的错误无法编译:http://msdn.microsoft.com/en-Us/library/bb384253(v = vs.90).aspx
然而,由于界面显然是公开的,所以这没有任何意义.这可能是什么错误?
我正在尝试创建一个实体类,它将通过只读属性公开相关集合,如下所示:
public class MyEntity: Entity
{
public int Id{ get; private set; }
private IList<RelatedEntity> _relatedEntities = new List<RelatedEntity>();
public IReadOnlyList<RelatedEntity> RelatedEntities => _relatedEntities.ToList().AsReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
构建器类如下所示:
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
builder.HasKey(x=>x.Id);
builder.Property<IReadOnlyList<RelatedEntity>>("RelatedEntities")
.HasField("_relatedEntities ")
.UsePropertyAccessMode(PropertyAccessMode.Field);
}
Run Code Online (Sandbox Code Playgroud)
它可以构建,但在运行时崩溃,但有以下例外:
InvalidOperationException:“IList”类型的指定字段“_latedEntities”不能用于“IReadOnlyList”类型的属性“MyEntity.RelatedEntities”。只能使用可从属性类型分配的类型的支持字段。
您能提供一个如何处理这个问题的工作示例吗?
我试图让我的 DbContext 在没有跟踪的情况下工作。
public class MyContext: DbContext
{
public MyContext()
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
...
}
Run Code Online (Sandbox Code Playgroud)
另外,在每次 Add(..) 或 Update(..) 之后,我都会删除对新实体的跟踪:
_context.Users.Add(user);
await _context.SaveChangesAsync();
_context.Entry(user).State = EntityState.Detached;
Run Code Online (Sandbox Code Playgroud)
如果我添加(或更新)一个引用现有实体(意味着已存储在数据库中)的新实体,就会出现问题。
例如:
var section = new Section();
_context.Sections.Add(section);
await _context.SaveChangesAsync();
_context.Entry(section).State = EntityState.Detached;
...
var user = new User
{
Name = "Alex",
Section = section
}
_context.Users.Add(user);
await _context.SaveChangesAsync();
Run Code Online (Sandbox Code Playgroud)
结果出现错误:
System.ArgumentException: '已添加具有相同键的项目。钥匙:1'
我怎样才能解决这个问题?
我有两个简单的POCO课程; 我试图MyY通过一个实例获得低于水合物的属性Y.我已经尝试了很多方法来做到这一点,并认为我可能会遗漏一些明显或简单的东西.
public class X
{
public int Id { get; set;}
public virtual Y MyY { get; set; }
}
public class Y
{
public int Id { get; set; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
我在我DbContext的构造函数的子类中通过这个调用关闭了延迟加载:
Configuration.LazyLoadingEnabled = false;
Run Code Online (Sandbox Code Playgroud)
检索时X我试过了
context.Set<X>.Include("MyY").FirstOrDefault(x => ....);
Run Code Online (Sandbox Code Playgroud)
这没用.我试过了
var result = context.Set<X>.FirstOrDefault(x => ....);
context.Entry(result).Reference("MyY").Load();
Run Code Online (Sandbox Code Playgroud)
哪个有效,但需要两次往返数据库.我试过了
context.Set<X>.Select(x => new { X = x, Y = x.MyY }).FirstOrDefault(x => ...);
Run Code Online (Sandbox Code Playgroud)
这也有效,但"削弱"我的模型(通常投射到一个新类型并不是那么糟糕,但这些EF POCO的"形状"适用于我稍后将通过WCF发送的DTO).
我终于尝试virtual从另一个问题MyY的 …
我对ASP.NET MVC 3的大部分知识来自阅读Adam Freeman和Steven Senderson撰写的Pro ASP.NET MVC 3 Framework一书.对于我的测试应用程序,我试图非常密切地坚持他们的例子.我正在使用存储库模式加上Ninject和Moq,这意味着单元测试工作得很好(即无需从数据库中提取数据).
在本书中,存储库的使用方式如下:
public class EFDbTestChildRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<TestChild> TestChildren
{
get { return context.TestChildren; }
}
public void SaveTestChild(TestChild testChild)
{
if (testChild.TestChildID == 0)
{
context.TestChildren.Add(testChild);
}
else
{
context.Entry(testChild).State = EntityState.Modified;
}
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
这是与之相关的DbContext:
public class EFDbContext : DbContext
{
public DbSet<TestParent> TestParents { get; set; }
public DbSet<TestChild> TestChildren { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
请注意:为了简化这个提取的例子,我在这里省略了接口ITestChildRepository,然后Ninject会使用它.
在其他来源中,我看到了一个更通用的存储库方法,其中一个存储库足以满足整个应用程序的需要.显然在我的情况下,我最终在我的应用程序中列出了相当多的存储库列表 - 基本上我的域模型中的每个实体都有一个.不确定这两种方法的优缺点 - 我只是按照这本书的安全性来做.
最后得到我的问题:每个存储库都有自己的DbContext …
repository-pattern entity-framework-4 asp.net-mvc-3 dbcontext
在带有Entity Framework的ASP .NET MVC 3中,我有一个域对象,它具有引用其他对象的导航属性,如下所示:
public class Person
{
public String Name {get;set;}
public Guid CompanyID{get;set;}
[ForeignKey(CompanyID)]
public virtual CompanyType Company{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)
当我创建Person的实例并尝试将其添加到数据库时,DBContext会保留此实体"Person"的缓存并将其发送到数据库.所以稍后在同一个上下文实例的生命周期中,当我尝试访问此实体时,Company字段始终为null,因为导航属性永远不会更新.
有没有办法用数据库中存在的内容更新导航属性?
延迟加载已打开.
entity-framework navigation-properties ef-code-first asp.net-mvc-3 dbcontext
我有以下是抛出一个SqlParameter已经被catch块中的另一个SqlParameterCollection异常包含.
我觉得奇怪的是,我们无处可创造一个SqlParameterCollection.每次我们创建一个新实例,所以SqlParameter从不使用过多次.另一个奇怪的是,它test包含来自存储过程的正确结果,并将结果返回给调用方法,但是当我再次从第一行3开始执行4时,它决定进入catch块.不在33我期望它发生的位置...如果它帮助我们使用CodeFirst生成工具从ObjectContexta 切换到a DbContext.使用的所有其他数据库交互和存储过程都按预期工作.
1 try
2 {
3 tempMessages = Context.CheckExistingTables(importSession.ImportSessionID).ToList();
4 }
5 catch (Exception e)
6 {
7 this.LogError("Error validating the import file entities", e);
8 tempMessages.Add(new ErrorMessage() { ErrorType = 3, Message = string.Format("Error validating the import file entities: {0}", e.Message) });
9 }
...
20 public IEnumerable<ErrorMessage> CheckExistingTables(Guid? importSessionID)
21 {
22 SqlParameter …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.
那么如何实现添加/删除功能呢?
我本打算在启动时调用此方法,但它不在任何地方引用:
dbContext.Database.Migrate();
Run Code Online (Sandbox Code Playgroud)
类型
DatabaseFacade不包含 的定义,Migrate并且找不到Migrate类型的扩展方法DatabaseFacade(您是否缺少 using 指令或程序集引用?
那么我缺少哪个使用/程序集?
dbcontext ×10
c# ×8
.net ×1
asp.net-mvc ×1
dbset ×1
ef-core-3.0 ×1
ef-core-3.1 ×1
entity-framework-migrations ×1
nsubstitute ×1