标签: self-tracking-entities

我怎么知道我是否应该使用自我跟踪实体或DTO/POCO?

有什么问题我可以问自己我们的设计,以确定我们是否应该在我们的应用程序中使用DTO或自我跟踪实体?

以下是我所知道的一些需要考虑的事项:

  • 我们有一个带有WPF/MVVM客户端,WCF服务器和MS SQL数据库的标准n层应用程序.
  • 用户可以定义自己的接口,因此WCF服务所需的数据会根据用户为自己定义的接口而更改
  • 模型在客户端和服务器端都用于验证.我们不会直接约束DTO或STE
  • 某些模型包含在需要时从WCF服务延迟加载的属性
  • 数据库层阻塞多个服务器/数据库
  • 服务器端有权限检查会影响数据的返回方式.例如,某些数据根据用户的角色部分或完全屏蔽
  • 我们的资源有限(时间,人力等)

那么,我怎样才能确定哪些适合我们?我之前从未使用EF,所以我真的不知道STE是否适合我们.

我见过人们建议从STE开始,只有当它成为一个问题时才实施DTO,但是我们目前有DTO并且正在尝试决定使用STE是否会让生活变得更轻松.我们在这个过程中已经足够早,切换不会花费太长时间,但我不想切换到STE只是为了发现它对我们不起作用并且必须切换回来.

wcf poco n-tier-architecture entity-framework-4 self-tracking-entities

8
推荐指数
1
解决办法
3369
查看次数

实体框架4中是否允许可以为空的外键?

我在更新Entity Framework实体中的外键时遇到问题.我正在使用自我跟踪实体并且具有一些具有某种关系的实体,其中外键也作为属性存在(EF4的新特征之一).密钥(整数)标记为Nullable并且修复了并发模式.

具体来说,我有一个与确认用户有很多到0..1关系的Alarm实体.(用户可以确认多个警报,但只能由零个或一个用户确认警报).

实体定义(简化):

Alarm properties
Id      Int32   non-nullable  identity entity key
UserId  Int32   nullable concurrency mode fixed
Alarm navigation properties
User    0..1 multiplicity

User properties
Id      Int32   non-nullable  identity entity key
Name    String  non-nullable
Run Code Online (Sandbox Code Playgroud)

在我的自我跟踪实体中,确认用户ID按预期自动生成为Nullable,但是如果我将用户分配给已经持久的警报并运行ApplyChanges,则自我跟踪上下文扩展会尝试设置原始值(null) EF上下文(在上下文扩展中的SetValue中),但是以静默方式跳过,因为EdmType的ClrEquivalentType是一个不可为空的Int32.

自动生成的扩展码:

    private static void SetValue(this OriginalValueRecord record, EdmProperty edmProperty, object value)
    {
        if (value == null)
        {
            Type entityClrType = ((PrimitiveType)edmProperty.TypeUsage.EdmType).ClrEquivalentType;
            if (entityClrType.IsValueType &&
                !(entityClrType.IsGenericType && typeof(Nullable<>) == entityClrType.GetGenericTypeDefinition()))
            {
                // Skip setting null original values on non-nullable CLR types because the ObjectStateEntry …
Run Code Online (Sandbox Code Playgroud)

entity-framework nullable optimistic-concurrency self-tracking-entities

7
推荐指数
1
解决办法
5815
查看次数

如何让Entity Framework仅更新在SQL生成中修改的属性?

我正在使用Entity Framework和自跟踪实体T4模板,默认情况下,它会生成一个SQL查询,在UPDATE语句中设置实体上的所有属性.我只想要一个包含已修改属性的UPDATE语句.

我修改了书中指定的T4模板:实体框架配方:问题解决方案方法页面503.

我在T4模板中改为这一行:

OriginalValueMembers originalValueMembers = new OriginalValueMembers(false, metadataWorkspace, ef);
Run Code Online (Sandbox Code Playgroud)

使实体跟踪每个属性更改而不是仅跟踪实体已更改.

并且

context.ObjectStateManager.ChangeObjectState(entity, EntityState.Unchanged);
Run Code Online (Sandbox Code Playgroud)

进行这些更改后,我得到了所需的SQL语句结果,只有UPDATE语句中的修改后的值/属性.然而,有一个奇怪的副作用.将可空的INT属性从null更新为null以外的值时,Entity Framework会忽略该属性的更改.自跟踪模型使用准确的OriginalValue null显示ChangeTracker中的更改,但是当Entity Framework尝试生成UPDATE SQL时,如果原始值为null且新值不为null,则它不会看到该属性更改.如果原始值不为null并且值发生更改,我就会工作.

它似乎对从null到非null值的字符串属性工作正常,但是int?不管用.

有没有人有任何想法?

linq-to-entities entity entity-framework entity-framework-4 self-tracking-entities

7
推荐指数
1
解决办法
1938
查看次数

在EF 4.1上使用ObjectContext与DbContext的存储库实现之间的区别

什么可以是更好的STE实现,我听说DbContext是用EF实现Repo的最简单方法,我个人利用了EntityState,但ObjectContext上有任何成员可以为我的CRUD操作提供更多的功能.回购?今天我正在使用像这样的GenericRepository:

public class GenericRepository<TEntity> where TEntity : class
    {
        internal DbContext context;
        internal DbSet<TEntity> dbSet;

        public GenericRepository(DbContext context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }

        public virtual IEnumerable<TEntity> Get(
            Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            string includeProperties = "")
        {
            IQueryable<TEntity> query = dbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (orderBy != null)
            {
                return …
Run Code Online (Sandbox Code Playgroud)

repository-pattern self-tracking-entities entity-framework-4.1

6
推荐指数
1
解决办法
5728
查看次数

许多查询和过多的打开/关闭相同的连接

我必须一个接一个地重新计算大量实体的值.

在此过程中,所有自跟踪实体都在同一个ObjectContext中进行更改.对于需要处理的每个实体,必须从数据库中提取少量数据.这导致了许多相同的SQL查询,但使用了不同的参数.

我正在使用Solutions Design的ORM Profiler软件来分析发送到数据库的查询.

查询本身对我来说似乎没问题.它们很短,不需要太多时间来执行.

但是,我对分析器如何显示查询的实际处理方式感到困惑:

在此输入图像描述

如您所见,它保持打开和关闭相同的数据库连接.

现在,看一下单个Open/Query/Close连接的时间:

在此输入图像描述

看起来打开和关闭数据库连接会浪费时间.

看完这个答案后,我改变了我的代码所以现在它看起来像这样:

using (var connection = new EntityConnection(ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString))
{
    using (var context = new MyEntities(connection))
    {
        // ...
Run Code Online (Sandbox Code Playgroud)

我现在可以看到它仍然使用相同的连接(这很好),但是,连接仍然在查询之间保持关闭和打开.

Gert Arnold建议我在使用上下文之前明确打开连接.然后我修改了我的代码,看起来像这样:

using (var connection = new EntityConnection(ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString))
{
    connection.Open();
    using (var context = new MyEntities(connection))
    {
        // ...
Run Code Online (Sandbox Code Playgroud)

现在它有效!每个查询都发送到同一个数据库连接:

在此输入图像描述

我现在很好奇为什么在使用上下文之前需要打开连接?

c# database-connection entity-framework-4 self-tracking-entities

6
推荐指数
1
解决办法
2322
查看次数

如何跟踪在CRUD场景中从ObservableCollection中删除的对象?

在我们的多层业务应用程序中,我们拥有ObservableCollections从服务调用返回的自我跟踪实体.

我们的想法是希望能够从集合客户端获取实体,添加,更新和删除它们,然后将这些更改发送到服务器端,并将它们保存到数据库中.

自我跟踪实体,正如其名称所暗示的那样,可以自己跟踪其状态.当创建一个新的STE时,它具有Added状态,当你修改一个属性时,它设置Modified状态,它也可以有Deleted状态,但是当从一个ObservableCollection(显然)中删除实体时,不会设置这个状态.如果您想要这种行为,您需要自己编写代码.

在我当前的实现中,当从中删除实体时ObservableCollection,我将其保存在阴影集合中,这样当ObservableCollection发送回服务器时,我可以发送已删除的项目,因此实体框架知道删除它们.

有点像:

protected IDictionary<int, IList> DeletedCollections = new Dictionary<int, IList>();

protected void SubscribeDeletionHandler<TEntity>(ObservableCollection<TEntity> collection)
{
    var deletedEntities = new List<TEntity>();
    DeletedCollections[collection.GetHashCode()] = deletedEntities;

    collection.CollectionChanged += (o, a) =>
        {
            if (a.OldItems != null)
            {
                deletedEntities.AddRange(a.OldItems.Cast<TEntity>());
            }
        };
}
Run Code Online (Sandbox Code Playgroud)

现在,如果用户决定将更改保存到服务器,我可以获取已删除项目的列表,并将其发送到:

ObservableCollection<Customer> customers = MyServiceProxy.GetCustomers();

customers.RemoveAt(0);

MyServiceProxy.UpdateCustomers(customers);
Run Code Online (Sandbox Code Playgroud)

此时,UpdateCustomers如果删除了任何项目,该方法将验证我的阴影收集,并将它们发送到服务器端.

这种方法很好,直到你开始考虑这些影子集合的生命周期.基本上,当ObservableCollection收集垃圾时,无法知道我们需要从字典中删除阴影集合.

我提出了一些复杂的解决方案,基本上在这种情况下进行手动内存管理.我保持WeakReferenceObservableCollection,并每隔几秒钟我检查,看看是否引用是无效的,在这种情况下,我删除了阴影集合.

但这似乎是一个可怕的解决方案......我希望StackOverflow的集体天才可以为更好的解决方案提供帮助.

编辑:

最后我决定继承子类化ObservableCollection.生成服务代理代码,因此更改它以返回我的派生类型是一个相对简单的任务.

感谢您的帮助!

lifecycle entity-framework observablecollection self-tracking-entities

5
推荐指数
1
解决办法
2028
查看次数

在我们的解决方案中将实体框架放在何处?

好的,我们有一个包含以下项目的解决方案:

  • 商业逻辑
  • 实体
  • 数据访问
  • 公用事业
  • 单元测试
  • 用户界面

它是一个非常大的企业级应用程序.我的问题是,我们在哪里放置实体框架?一方面,EF看起来像数据访问技术,应该进入DataAccess项目.但另一方面,它会生成自己的实体,这些实体应放在我们已经很大的实体项目中.

哪个项目更适合实体框架?

是否有可能将实体与EF中的持久性逻辑分开?

c# entity-framework data-access-layer entity-framework-4 self-tracking-entities

5
推荐指数
1
解决办法
2039
查看次数

不再推荐自我跟踪实体.什么是?

阅读有关EF 5.0和n层解决方案的msdn信息,请参阅链接,似乎MS不推荐使用STE,并且不建议使用POCO/DTO方式,因为它很难说.

并非所有(可能不是很多?)应用程序都适合使用WCF数据服务.那么走的路是什么?我的场景是一个当前的大型服务器(WebServices)应用程序,有许多客户端(只有我们自己的),主要是WinForms.今天,DataSet用于发送数据并跟踪对SQL Server数据库的更改.

我们现在开始用WCF替换WebServices,并且还在考虑使用实体框架.我们不需要代码或迁移,因为我们已经有了数据库,并且有许多存储过程将被重用.由于我们对客户不是我们自己的任何问题,STE似乎是一个不错的选择,但我们不想开始使用EF团队显然不再推荐的东西了.POCO/DTO也是一种替代方案,尤其是对客户的明确分离.我知道CUD还有更多的工作要做,但是建议是远离它是如此困难,然后我不知道我们是否想走这条路.

然后,根据建议我们应该使用WCF数据服务或Web API,但这实际上不是基于操作的服务的替代方案,需要灵活的协议/格式等.

所以我的问题是,今天最佳做法是什么?

c# wcf entity-framework self-tracking-entities

5
推荐指数
1
解决办法
2168
查看次数

如果不再推荐自我跟踪实体,那么改变复杂实体关系的前进道路是什么?

自从它首次问世以来,我一直在使用EF.用于在3.5中手动构建POCO,很高兴看到EF4.0中的自跟踪实体(STE).

我在一些非常大的项目中使用了STE(500多个实体,一些有多个模型).在这些项目中,我使用通用存储库和通用工作单元来持久化实体,即2个小类通用类没有映射.通过选择核心实体作为"聚合根",在客户端添加和更新其他实体,并将包含这些更改的核心实体图发送到WCF服务并在创建存储库<[核心实体]的逻辑层中使用]>并使用UnitOfWork <[核心实体]>.保存(存储库<[核心实体]>)以将STE及其子节点持久保存到数据库中.

现在微软建议我们不要使用STE.看到这篇文章

所以我的问题是,对于那些将客户端更改持久保存到使用EF的WCF服务的应用程序,Microsoft现在推荐的模式是什么?

我创建了一个EF5模型并检查了生成的代码.WCF服务没有属性,即DataContract,DataMember等

EF4有一个"支持WCF的ADO.NET DbContext生成器"模板,但没有EF5等价物.

一个站点建议我应该使用部分类文件并使用这些属性修饰该文件中的相同属性.但除非.net 4.5引入了部分属性,否则我无法看到如何做到这一点.

一篇博客 建议使用DTO和Automapper,这意味着更多的映射容易出错; 特别是当实体字段改变类型时.

所以现在DBContext生成的代码类没有启用Service,这是否意味着我们需要编写另一组类(POCO):

  • 在查询数据库之后,需要从DBContext生成的代码类映射.
  • 保存WCF服务客户端的数据状态
  • 可由客户端更新
  • 由客户映射
  • 能够保持更改状态,以便将其发送回WCF服务
  • 需要映射到DBContext生成的代码类以实现持久性

看起来我们刚刚向EF3迈进了一大步.

如果您对在硬件上运行的客户端和服务进行编码,则无需担心客户端属于您的数据结构.

如果您还需要向非.NET客户端公开一些服务方法,那么无论如何都应该为这些服务执行上述5点,并在这些场合使用DTO和Automapper.这些应该在不同的WCF服务中,但是针对相同的逻辑实现图层映射后.

但是,在大多数软件团队的Web应用程序的日常构建中,有多少这类非.NET客户端服务被创建?

这个最新的建议令人困惑,因为它没有被解释为什么STE总是构思错误,现在是什么,建议的模式用于持久化客户端更改使用EF的WCF服务.

任何人都可以告诉我哪里可以找到解决这个架构设计问题的好资源?

PS

请不要推荐WCF数据服务或WCF RIA,因为我们需要对客户端检索和保存数据的方式进行大量控制.

请不要推荐Code First,因为我们使用Database First,因为我们希望拥有并且需要控制该数据库的结构而不必为我们生成.

wcf entity-framework self-tracking-entities

5
推荐指数
1
解决办法
260
查看次数

替换实体框架6中的自追踪实体

我相信大多数.NET开发人员必须以某种方式面对这个问题.问题很简单,我正在将我的项目从.NET 4升级到.NET 4.5.1.到目前为止,升级非常顺利.但是当我从EF4升级到EF6时,我在查询中遇到了很多错误.其中一些与重命名我所做的上下文有关,但对于与自我跟踪实体相关的错误,我有点困惑.

自我跟踪实体是我项目的主要部分,EF6不支持它们意味着我将不得不重写我的DAL的主要部分.我试图找出但在EF6中找不到STE的替代品.

有没有人知道这种情况?我是否必须重写我的STE依赖查询.答案不应该包括解释为什么微软决定放弃STEs,因为我已经通过许多博客解释了这一点.

self-tracking-entities .net-4.5 entity-framework-6

5
推荐指数
1
解决办法
1519
查看次数