Bre*_*ell 5 c# t4 entity-framework interface entity-framework-6
我正在使用Database-First方法.
我创建了一个TextTemplate(.tt)文件,它从EDMX文件生成接口,我也修改了由EDMX文件(项目项)包含/生成的原始TextTemplate文件,让生成的类实现这些接口.
namespace TestSolution.Domain.Entities
{
using System;
using System.Collections.Generic;
using TestSolution.Domain.Entities;
public partial class Person : IPerson
{
public Person()
{
//this.CrewMembers = new HastSet<CrewMember>();
this.CrewMembers = new HashSet<ICrewMember>();
}
public Person(IPerson iPerson)
{
this.PersonID = iPerson.PersonID;
this.First = iPerson.First;
this.Last = iPerson.Last;
//this.CrewMembers = new HastSet<CrewMember>();
this.CrewMembers = new HashSet<ICrewMember>();
}
public int PersonID { get; set; }
public string First { get; set; }
public string Last { get; set; }
//public virtual ICollection<CrewMember> CrewMembers { get; set; }
public virtual ICollection<ICrewMember> CrewMembers { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码示例中所看到的,我还添加了一个构造函数,该构造函数接受初始化Person类的接口...
namespace TestSolution.Domain.Entities
{
using System;
using System.Collections.Generic;
public interface IPerson
{
int PersonID { get; set; }
string First { get; set; }
string Last { get; set; }
//ICollection<CrewMember> CrewMembers { get; set; }
ICollection<ICrewMember> CrewMembers { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
该CrewMember级和ICrewMemberInteface包含:
IsCaptain和IsAssigned) Int PersonID作为财产,Int CrewMemberID作为财产, Person Person当然的人.(我也试过IPerson Person了).我打算ICollection<ICrewMember>用于导航.然后使用实现这些接口的DTO/Model/ModelView对象/类.
当我ICollection<InterfaceTEntity>在导航属性中生成类型时,我没有看到任何问题..使用EntityFramework ..直到我尝试使用相同的上下文更新两个实体:context.CrewMembers并且context.People在同一个函数中.
public void UpdateCrewMemberModel(CrewMemberModel CrewMember)
{
var query = (from crewMember in UnitOfWork.DataContext.CrewMembers
where crewMember.CrewMemberID == CrewMember.CrewMemberID
select crewMember).First<CrewMember>();
query.IsAssigned = CrewMember.IsAssigned;
query.IsCaptain = CrewMember.IsCaptain;
// Exception is thrown here
var queryPerson = (from person in UnitOfWork.DataContext.People
where person.PersonID == query.PersonID
select person).First<Person>();
queryPerson.First = CrewMember.Person.First;
queryPerson.Last = CrewMember.Person.Last;
//Note that UnitOfWork uses a Factory Repository Pattern;
//Commit just calls on UnitOfWork.DataContext.SaveAll() Method
UnitOfWork.Commit();
}
Run Code Online (Sandbox Code Playgroud)
我遇到/看到的问题似乎与EntityFramework的更改跟踪功能有关.但是,它实际上是以EntityFramework本身的异步操作为根.
如果我调试并逐步执行上述方法,则没有异常,并且数据库/表正确更新..
如果我在声明queryPerson的语句之前没有捕获调试点的情况下运行它,它将抛出一个异常(一个关于Person.CrewMembers的误导性异常ICollection<T>).
这当然似乎是一个时间问题
我试图删除ICollection <>属性上的虚拟属性; 没有影响这个问题.
我试图删除Lazy Loading; 没有影响这个问题.
我试图在查询之间提交更改; 没有影响这个问题.
我试图执行FirstAsync<>查询使用; 但我不确定我是否正在使用它......我仍在摆弄这种方法.
System.Data.Entity.Core.EntityException
{"The navigation property 'CrewMembers' on entity of type 'System.Data.Entity.DynamicProxies.Person_1A1EF42B1FC8D2DD0084F803201DE1DE4CF6E704C5AE129D954BD5BEAB55826C' must implement ICollection<T> in order for Entity Framework to be able to track changes in collections."}
Source: EntityFramework
at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.CheckIfNavigationPropertyContainsEntity(IEntityWrapper wrapper)
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedEntity, Boolean applyConstraints)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference`1.set_ReferenceValue(IEntityWrapper value)
at System.Data.Entity.Core.Objects.DataClasses.EntityReference.SetEntityKey(EntityKey value, Boolean forceFixup)
at System.Data.Entity.Core.Objects.EntityEntry.FixupEntityReferenceToPrincipal(EntityReference relatedEnd, EntityKey foreignKey, Boolean setIsLoaded, Boolean replaceExistingRef)
at System.Data.Entity.Core.Objects.EntityEntry.FixupReferencesByForeignKeys(Boolean replaceAddedRefs, EntitySetBase restrictTo)
at System.Data.Entity.Core.Objects.ObjectStateManager.FixupReferencesByForeignKeys(EntityEntry newEntry, Boolean replaceAddedRefs)
at System.Data.Entity.Core.Objects.ObjectStateManager.AddEntry(IEntityWrapper wrappedObject, EntityKey passedKey, EntitySet entitySet, String argumentName, Boolean isAdded)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet)
at lambda_method(Closure , Shaper )
at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at TestSolution.Infrastructure.Service.CrewMemberService.UpdateCrewMemberModel(CrewMemberModel CrewMember) in c:\Users\brett.caswell\Documents\Visual Studio 2012\Projects\TestSolution\TestSolution.Infrastructure.Service\Services\CrewMemberServices.cs:line 67
TargetSite: {Boolean CheckIfNavigationPropertyContainsEntity(System.Data.Entity.Core.Objects.Internal.IEntityWrapper)}
Run Code Online (Sandbox Code Playgroud)
虽然要问这个问题可能是不正确地确定了我所拥有的问题......
当使用Generic Type接口与生成的类的导航属性中的ICollection时,我如何处理在UpdateCrewmMemberModelEntityFramework内/从EntityFramework中发生的潜在不安全的线程实例(在我的方法中)?
如果您尝试使用接口作为实体(EF 不支持),通常会收到此错误。CrewMember 实际上是一个接口吗?
如果它不是一个接口,而是一个派生自接口的类,则 EF 可能在某些时候会感到困惑。您是否正在进行 Fluent 配置?也许您正在尝试映射到会引发此错误的基类或接口?
您的代码实际上有点令人困惑,因为您应该使用“工作单元”,但您直接访问您的 dbcontext,因此有效地绕过了 UoW,但随后在 UoW 上调用 Commit() ...我会建议您可能需要重新考虑这里的数据设计,并且可能完全摆脱 UoW,因为 EF 已经是一个工作单元。