假设我们已经设置的界面呈现问题”域:IUser, IAddressBook, IComment
等。该假设IUser
定义如下:
public interface IUser : IAmIdentifiedEntity<int>, IHaveName
{
string FullName { get; set; }
string Email { get; set; }
bool ReceiveNotification { get; set; }
}
public interface IHaveName
{
string Name { get; set; }
}
在我的应用程序只用提到的合同,例如:
public IUser GetUser(string userName)
{
return Warehouse.GetRepository<IUser>().GetAll()
.First(u => u.Name == userName);
}
正如你所看到的,我使用一些网关获取数据。库”方法GetAll()
返回IQueryable<TEntity>
,所以可以建立一些复杂的查询,并使用延迟加载的所有优势。当我介绍它时,我想到了未来Linq2Sql的应用。
一段时间以来,在开发客户端代码,我们使用“内存”实现数据存储。所以一切正常。但现在是将域绑定到SQL Server的时候了。所以我开始在LINQ2SQL实现所有的基础设施......当制作简单的解决方案(由弗雷德里克Kalseth的article启发),得到了第一个例外,我已经意识到这个想法的所有悲伤...这里是implmentation的IUser
:
public partial class USER : IUser
{
int IHaveID<int>.ID
{
get { return USERID; }
}
string IHaveName.Name
{
get { return USERNAME; }
set { USERNAME = value; }
}
string IUser.FullName
{
get { return USERFULLNAME; }
set { USERFULLNAME = value; }
}
// ... same approach for other properties
}
在这里 - 例外:
Exception: System.NotSupportedException:
The member 'Data.IHaveName.Name' has no supported translation to SQL.
这是明显的例外 - LINQ2SQL提供商并不了解外部接口,但我应该怎么解决呢?我不能改变域接口返回Linq.Expression,如:
Expression<Func<string>> IHaveName.Name
{
get { return (() => USERNAME); }
set { USERNAME = value(); }
}
,因为它打破了所有的域接口当前的代码使用,而且我不能Expression<Func<int>>
取代int
因为宗教信仰的:)
也许,我应该写自定义表达式访问者查询与它的内部子AST跳过” AST主叫IUser.SomeProperty
和替换它...
你能提供上你的想法?
UPDATE。在这里,我应该写一些关于Repository
的实现。看看GetAll()
来源:
public IQueryable<TEntity> GetAll()
{
ITable table = GetTable();
return table.Cast<TEntity>();
}
protected ITable GetTable()
{
return _dataContext.GetTable(_implType);
}
在我的例子,TEntity <=> IUser
和_implType <=> typeof(USER)
更新2我发现related question,其中OP有一个相似的问题:需要具体的ORM实体和它之间的一些桥梁域实体。我发现有趣的the answer:作者建议创建表达式访问者,它将执行实体之间的转换(ORM < => Domain)。
有什么新建议? – ajukraine