首页 \ 问答 \ 如何让Linq2Sql了解自定义类型?(How to make the Linq2Sql understand custom types?)

如何让Linq2Sql了解自定义类型?(How to make the Linq2Sql understand custom types?)

乡亲!

假设我们有一组接口提出问题'域: 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);
}

如您所见,我正在使用一些网关来获取数据。 Repository'方法GetAll()返回IQueryable<TEntity> ,因此可以构建一些复杂的查询并使用延迟加载的所有好处。 当我介绍它的时候,我想到了Linq2Sql的设备。

有一段时间,在开发客户端代码时,我们使用“内存中”实现数据存储。 所以一切正常。 但现在是将域绑定到SQL Server的时候了。 所以我已经开始在Linq2Sql上实现所有的基础设施......当得到简单的解决方案(受到Fredrik Kalseth 文章的启发)并得到第一个例外时,我已经意识到这个想法的所有悲伤......这是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 :)

也许,我应该写自定义Expression访问者跳过查询'AST调用IUser.SomeProperty并用它的内部子AST替换它...

你能提出你的想法吗?

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.我发现了相关的问题 ,OP有一个类似的问题:需要在具体的ORM实体和它的域实体之间建立一些桥梁。 我发现有趣的答案 :作者建议创建表达式访问者,它将执行实体之间的转换(ORM <=>域)。


folks!

Suppose we have set of interfaces that presents problem' domain: IUser, IAddressBook, IComment and so on. The assume that IUser is defined as follows:

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; }
}

In my application I use only mentioned contracts, for example:

public IUser GetUser(string userName)
{
    return Warehouse.GetRepository<IUser>().GetAll()
        .First(u => u.Name == userName);
}

As you can see, I'm using some gateway to get data. Repository' method GetAll() returns IQueryable<TEntity>, so it is possible to build some complex query and use all benefits of lazy loading. When I was introducing it, I thought about appliance of Linq2Sql in future.

For some time, while developing client code, we were using 'in-memory' implementation of data storage. So everything works fine. But now it's a time to bind domain to SQL Server. So I've started to implement all the infrastructure upon Linq2Sql... And when made simple solution (inspired by article of Fredrik Kalseth) and got first exception, I've realized all sadness of that idea... Here is implmentation of 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
}

And here - exception:

Exception: System.NotSupportedException: 
    The member 'Data.IHaveName.Name' has no supported translation to SQL.

This is obvious exception - Linq2Sql provider doesn't understand external interfaces, but how should I resolve it? I can't change domain interfaces to return Linq.Expression like:

Expression<Func<string>> IHaveName.Name
{
    get { return (() => USERNAME);  }
    set { USERNAME = value(); }
}

because it breaks all the current code usage of domain interfaces and moreover i can't replace int with Expression<Func<int>> because of religious beliefs :)

Maybe, I should write custom Expression visitor to skip in query' AST calling of IUser.SomeProperty and replace it with it's inner sub-AST...

Can you provide your thoughts on it?

UPDATE. Here I should write something about Repository implementation. Look at GetAll() source:

public IQueryable<TEntity> GetAll()
{
    ITable table = GetTable();
    return table.Cast<TEntity>();
}

protected ITable GetTable()
{
    return _dataContext.GetTable(_implType);
}

In my example, TEntity <=> IUser and _implType <=> typeof(USER)

UPDATE 2. I've found related question, where OP has an alike problem: need some bridge between concrete ORM entities and it's domain entities. And I've found interesting the answer: author suggested to create expression visitor, which will perform convertion between entities (ORM <=> Domain).


原文:https://stackoverflow.com/questions/7901617
更新时间:2022-10-16 06:10

最满意答案

删除按钮的浮动,所有输入都是内联块

.login input{
   display: inline-block;
}

DEMO


remove the float of button, and all input are inline-block

.login input{
   display: inline-block;
}

DEMO

相关问答

更多
  • 按钮行为优先于标签行为。 它也无法工作,因为label需要一个for属性来定位输入的ID。 这里的解决方法是使用简单的标签而不是按钮,然后为标签指定按钮的样式。 这是一个显示这个的小提琴,当然你可以修改标签样式以接近原始按钮样式。 我希望这能实现你想做的事。 的jsfiddle 编辑:此外,您可以使用简单的display: none; 在您的无线电输入上隐藏它们。 更新了JSFiddle The button behavior have priority over the label behavior. A ...
  • 下面的CSS代码块是我需要强制有问题的元素采取其父母的全部宽度,并解决了问题。 #jssor_1 > div div div { width: 100%!important; } The block of CSS code below was all that I needed to force the problematic element to take on the full width of its parent and that solved the problem. #jssor_1 ...
  • 我无法按需要使用它。 作为解决方法,如果用户正在使用Android设备,我只需打开文件地址窗口即可将文档下载到本地存储。 我希望这是未来可以解决的问题。 var attachmentPromise = $http.get("/api/" + $routeParams.ID, { responseType: 'blob' }).then(function (result) { var file = new Blob([re ...
  • 好吧,看起来,当你在css的开始处设置了所有元素的转换时,就引发了这种行为。 我只是改变你的CSS的开始: CSS: * { font-family: sans-serif; } .button { border-radius: 40px; border: solid 2px; text-align: center; font-size: 18px; border-color: antiquewhite; padding: 8px; width: auto; curso ...
  • 搞定了。 罪魁祸首是: 大小调整 - 显然Chrome和Firefox对于使用相同字体的Em有多大的不同 位置相对vs绝对 - .custom-combobox类的相对位置在.custom-combobox比较时拧紧了定位。 我认为Chrome和Firefox的价值略有不同,相对于相对定位而言。 Got it working. The culprits were: em sizing - apparently Chrome and Firefox have different ideas of how bi ...
  • 为了使我的情况适用于所有浏览器,我必须结合我的原始语句和adelphus建议的语句(谢谢!),因为它们本身似乎都不适用于所有浏览器。 我的最后陈述是 if (window.screen.width < 800 || $('.l-header').css('position') == 'fixed' ) To make my situation work on all browsers I had to combine my original statement, and the statement as ...
  • 将其添加到您的CSS中 html, body { height: 100%; } Add this to your CSS html, body { height: 100%; }
  • 删除按钮的浮动,所有输入都是内联块 .login input{ display: inline-block; } DEMO remove the float of button, and all input are inline-block .login input{ display: inline-block; } DEMO
  • 这是与屏幕截图相关的问题。 代码正确,按钮在所有浏览器中都正确定位。 It is an issue related to the way screenshots are taken. The code is correct and the button is positioned correctly in all browsers.