C# 将域模型映射到具有不同主键数据类型的不同持久性存储
我需要为不同的客户开发一个应用程序,该应用程序需要针对不同的现有遗留数据库作为持久性存储,或者也可以使用自己的独立数据库完全独立运行 因此,我的方法是:C# 将域模型映射到具有不同主键数据类型的不同持久性存储,c#,entity-framework,ef-code-first,dynamics-crm-2011,C#,Entity Framework,Ef Code First,Dynamics Crm 2011,我需要为不同的客户开发一个应用程序,该应用程序需要针对不同的现有遗留数据库作为持久性存储,或者也可以使用自己的独立数据库完全独立运行 因此,我的方法是: 独立于最终的持久性存储开发域模型 如果需要,使用EF Code First存储库实现将其映射到自己的独立数据库 如果需要,使用其他存储库实现将其映射到遗留数据库系统 我知道一个事实,现有的目标系统之一是CRM 2011系统。“CRMRepository”实现最好使用MicrosoftCRM SDK,而不是直接针对底层SQL数据库 但是,CR
- 独立于最终的持久性存储开发域模型
- 如果需要,使用EF Code First存储库实现将其映射到自己的独立数据库
- 如果需要,使用其他存储库实现将其映射到遗留数据库系统
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
- 对于独立解决方案:使用基于代码优先的EF存储库,没有问题
- 对于以INT作为主键的现有数据库:将其映射到正确的主键属性,没有问题
- 但是,如何定位CRM后端?“Person”实体通常会映射到CRM中的“Account”实体,但是PK是accountid,它是一个GUID,与所有其他CRM实体一样
看起来您有两个选择
int-Id
和Guid
。这消除了显式强制转换的成本,并可能有助于类型安全。也意味着如果其他系统使用长
或字符串
作为id,您将遇到问题我也有类似的情况。不同类型的公司拥有不同的信息,处理方式也不同,并映射到以Int和GUI作为主键的旧表中 我最终得到的是一个带有GUID主键和所有共享公共数据的base(设置为abstract in EF)表,然后每个类型都有一个继承表(这些表的主键是base上的外键)。在这些表中,我能够声明关于特定类型的任何特定信息,并将它们链接到其他旧表或新表 在您的情况下,您可以有一个基本客户类型,但随后根据需要声明尽可能多的不同类型的客户,并在需要时对其进行扩展和链接。然后,您可以将其作为目标:
var baseCust = db.Customers.FirstOrDefault(x => x.Id == someId);
if(baseCust is CustTypeA)
{
// Access extended properties and Legacy tables (via lazy loading)
var custA = (CustTypeA)baseCust;
custA.SomeExtendedProperty = blah;
var oldCompletedOrders = custA.Orders.Where(x => x.Completed).ToList();
//etc
这给了我们前进的灵活性,让我们能够接触到他们想看到的所有旧垃圾
让我的所有域对象从抽象基类实体继承,然后使用属性“publictkey Id{get;set;}”,怎么样。或者,如果我允许在不同的域对象上使用不同类型的键,甚至是基于每个类。这是一个可行的解决方案吗?请记住,存储库的实现可以是从EF到NHibernate再到像CRM这样的定制回购的任何东西 您可以实现几个接口和一个基本存储库(我已经阅读了类似的东西)。请考虑下面的LIQPAD脚本(我只使用转储用于验证目的):
void Main()
{
var personList=新列表
{
新PersonSql
{
Id=1,
FirstName=“Some”,
LastName=“个人”
}
}.AsQueryable();
var repo=新的PersonRepo();
repo.Query=个人列表;
repo.GetById(1.Dump();
}
//在此处定义其他方法和类
//实体库
类BaseEntity
{
公钥Id{get;set;}
}
//常见结构
类PersonBase:BaseEntity
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
//id为int类型的实际实体
类PersonSql:PersonBase
{
}
//等等
类PersonNoSql:PersonBase
{
}
//在创建映射类时,您可能会根据数据源生成这些或对它们进行编码。
//存储库
界面假定
其中tenty:BaseEntity
{
IQueryable查询{get;set;}
TEntity GetById(TKeyI键);
//这里还有其他存储库方法
}
抽象类RepoBase:IRep
void Main()
{
var personList = new List<PersonSql>
{
new PersonSql
{
Id = 1,
FirstName = "Some",
LastName = "Person"
}
}.AsQueryable();
var repo = new PersonRepo();
repo.Query = personList;
repo.GetById(1).Dump();
}
// Define other methods and classes here
//entity base
class BaseEntity<TKey>
{
public TKey Id { get; set; }
}
//common constructs
class PersonBase<Tkey> : BaseEntity<Tkey>
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
//actual entity with type of int as the id
class PersonSql : PersonBase<int>
{
}
//and so on
class PersonNoSql : PersonBase<string>
{
}
//likley you would generate these or code them based on your data source when creating your mapping classes.
//repositories
interface IRepository<TEntity, TKeyI>
where TEntity : BaseEntity<TKeyI>
{
IQueryable<TEntity> Query {get; set;}
TEntity GetById(TKeyI key);
//Other Repository Methods here
}
abstract class RepoBase<TBaseEntity, TKeyB> : IRepository<TBaseEntity, TKeyB>
where TBaseEntity : BaseEntity<TKeyB>
{
//Base Implementations Here
public IQueryable<TBaseEntity> Query { get; set; }
public virtual TBaseEntity GetById(TKeyB key)
{
throw new NotImplementedException();
}
}
abstract class PersonRepoBase<TkeyType> : RepoBase<PersonBase<TkeyType>, TkeyType>
{
public override PersonBase<TkeyType> GetById(TkeyType key)
{
//Get a person.
throw new NotImplementedException();
}
}
//class PersonRepo : RepoBase<PersonNoSql, string>
//{
// public override PersonNoSql GetById(string id)
// {
// throw new NotImplementedException();
// }
//}
class PersonRepo : RepoBase<PersonSql, int>
{
public override PersonSql GetById(int id)
{
return Query.First(x => x.Id == id);
throw new NotImplementedException();
}
}