实体框架/Linq to sql 模型到业务模型
Posted
技术标签:
【中文标题】实体框架/Linq to sql 模型到业务模型【英文标题】:Entity Framework/Linq to sql model to business model 【发布时间】:2011-07-24 16:36:42 【问题描述】:我来自存储过程并手动创建数据访问层。我试图了解我应该在哪里将 Linq To SQL 或实体框架纳入我的正常计划。我通常将业务层与 DAL 层分离,并在两者之间使用存储库。
似乎人们要么使用生成的从 linq 到 sql 的类,通过使用部分类来扩展它们,要么进行完全分离并将生成的 linq 类映射到单独的业务实体。我偏爱单独的商业实体。但是,这似乎违反直觉。
我最近的一个项目使用了 DDD 和实体框架。当需要更新一个对象时,它将业务实体移动到 repistory 层,当进入 DAL 层时,它将创建一个上下文,然后重新查询该对象。它会更新值并重新提交。
我没有看到重点,因为数据上下文没有保存,需要额外的查询才能在更新之前获取对象。通常我会做更新(如果并发不是问题)
所以我的问题归结为:
-
将 linq to sql 生成的类分离到业务实体中是否有意义?
应该保存数据上下文还是不切实际?
感谢您抽出宝贵时间,确保我理解。我通常喜欢分开,因为它使即使在一些较小的项目中也更容易理解。
【问题讨论】:
【参考方案1】:我目前手动滚动我自己的 Dto 类和 Datacontext,而不是使用从 Linq 到 Sql 的自动生成的代码文件。为了提供我的解决方案架构/建模的一些背景,我有一个“合同”项目和一个“Dal”项目。 (也是一个“模型”项目,但我会尽量只关注 Dal)。手动滚动我自己的 Dtos 和 Datacontext,让一切变得更小更简单,我将在这里举几个例子说明我是如何做到的。
我从不返回 Dal 之外的 Dto 对象,事实上我确保将它们声明为内部的。我将它们返回的方式是将它们转换为接口(接口位于我的“合同”层中)。我们将创建一个简单的“PersonRepository”,实现“IPersonRetriever 和 IPersonSaver”接口。
合同:
public interface IPersonRetriever
IPerson GetPersonById(Guid personId);
public interface IPersonSaver
void SavePerson(IPerson person);
达尔:
public class PersonRepository : IPersonSaver, IPersonRetriever
private string _connectionString;
public PersonRepository(string connectionString)
_connectionString = connectionString;
IPerson IPersonRetriever.GetPersonById(Guid id)
using (var dc = new PersonDataContext(_connectionString))
return dc.PersonDtos.FirstOrDefault(p => p.PersonId == id);
void IPersonSaver.SavePerson(IPerson person)
using (var dc = new PersonDataContext(_connectionString))
var personDto = new PersonDto
Id = person.Id,
FirstName = person.FirstName,
Age = person.Age
;
dc.PersonDtos.InsertOnSubmit(personDto);
dc.SubmitChanges();
PersonDataContext:
internal class PersonDataContext : System.Data.Linq.DataContext
static MappingSource _mappingSource = new AttributeMappingSource(); // necessary for pre-compiled linq queries in .Net 4.0+
internal PersonDataContext(string connectionString) : base(connectionString, _mappingSource)
internal Table<PersonDto> PersonDtos get return GetTable<PersonDto>();
[Table(Name = "dbo.Persons")]
internal class PersonDto : IPerson
[Column(Name = "PersonIdentityId", IsPrimaryKey = true, IsDbGenerated = false)]
internal Guid Id get; set;
[Column]
internal string FirstName get; set;
[Column]
internal int Age get; set;
#region IPerson implementation
Guid IPerson.Id get return this.Id;
string IPerson.FirstName get return this.FirstName;
int IPerson.Age get return this.Age;
#endregion
您需要将“Column”属性添加到所有 Dto 属性,但是如果您注意到,如果您希望在界面上公开的字段之间存在一对一的关联,并且实际表列的名称,您不需要添加任何命名参数。在此示例中,我在数据库中的 PersonId 存储为“PersonIdentityId”,但我只希望我的界面使该字段显示为“Id”。
这就是我做 Dal 层的方式,我相信这个层应该是愚蠢的,真正的愚蠢。从某种意义上说,它仅用于 CRUD(创建、检索、更新和删除)操作是愚蠢的。所有业务逻辑都将进入我的“模型”项目,该项目将使用和利用 IPersonSaver 和 IPersonRetriever 接口。
希望这会有所帮助!
【讨论】:
这更有意义。我的问题是,这如何利用自动生成类的功能?看来,如果您想实现良好的分离,仍然需要做大量的管道工作。 如果你走这条路,你真的需要做很多事情,这就是为什么我自己不使用自动生成的类。在我看来,像这样手动滚动它们使事情更容易阅读,代码更少,体积更小,更容易调试,更好的分离等等。 所以主要使用 linq 来帮助从存储过程中抽象出来并使基本的 crud 操作更容易。好吧,这很有意义。我一直在研究泛型,试图弄清楚它是否可以用来帮助减少代码重复。 有时最好让存储过程处理数据库中复杂的业务规则,而 linq 有一种非常酷的缓存存储过程的方法,以减少过度听到的情况。如果这对您也有帮助,我可以发布“编译的 linq 查询”。 另外,请参阅此处以获取有关通用存储库的好帖子 - ***.com/questions/2587965/…以上是关于实体框架/Linq to sql 模型到业务模型的主要内容,如果未能解决你的问题,请参考以下文章
使用实体模型和 LINQ 的 C# WPF SQL 多表 CRUD