如何将工厂类与 linq for sql 一起使用?

发布于 2024-08-04 01:46:02 字数 1229 浏览 5 评论 0原文

我在数据库模型之上有一个模型,并将对象映射到我的存储库中。

然而,显然,无论我直接在 GetUsers 中“选择新的”还是“选择工厂结果”,这都会有所不同,如下所示。我在运行时收到错误,方法 CreateFromDbModel 没有转换为 sql (System.NotSupportedException)。

有办法解决这个问题吗?我能以某种方式修复它吗?

想要使用工厂方法的原因是我可能会在其他地方实例化对象并希望将“映射代码”保留在一个地方......

感谢您的任何评论, 安德斯

    public IQueryable<User> GetUsers(bool includeTeams)
    {
        return from u in _db.sc_Players
               where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam))
               select UserFactory2.CreateFromDbModel(u);
    }


    public static User CreateFromDbModel(sc_Player player)
    {
        return new User
                   {
                       Id = player.sc_PlayerID,
                       FirstName = player.FirstName.Trim(),
                       LastName = player.LastName.Trim(),
                       PresentationName = player.FirstName.Trim() + " " + player.LastName.Trim(),
                       LoginName = player.aspnet_User.LoweredUserName,
                       IsTeam = player.IsTeam,
                       Email = player.aspnet_User.aspnet_Membership.Email,
                       Password = player.aspnet_User.aspnet_Membership.Password
                   };
    }

I have a model on top of my database model and map the objects in my Repository.

However, apparently it makes a difference whether I "select new" directly in my GetUsers or "select factoryresult" as implemented below. I get the error at runtime, that the method CreateFromDbModel does not have a translation to sql (System.NotSupportedException).

Is there a way around this? Can I mend it somehow?

The reason for wanting to use the factory method is that I might instanciate objects elsewhere and want to keep the 'mapping code' in one place...

Thanks for any comments,
Anders

    public IQueryable<User> GetUsers(bool includeTeams)
    {
        return from u in _db.sc_Players
               where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam))
               select UserFactory2.CreateFromDbModel(u);
    }


    public static User CreateFromDbModel(sc_Player player)
    {
        return new User
                   {
                       Id = player.sc_PlayerID,
                       FirstName = player.FirstName.Trim(),
                       LastName = player.LastName.Trim(),
                       PresentationName = player.FirstName.Trim() + " " + player.LastName.Trim(),
                       LoginName = player.aspnet_User.LoweredUserName,
                       IsTeam = player.IsTeam,
                       Email = player.aspnet_User.aspnet_Membership.Email,
                       Password = player.aspnet_User.aspnet_Membership.Password
                   };
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

林空鹿饮溪 2024-08-11 01:46:02

该错误几乎解释了一切。

“方法 CreateFromDbModel 没有对 sql 的翻译 (System.NotSupportedException)”

您的 CreateFromDbModel 方法不是 sql 函数。在对象专门从服务器返回给您之前,您的应用程序将无法运行 CreateFromDbModel 函数。在对它们运行 CreateFromDbModel 之前,您很可能必须在查询中调用 ToList() 或类似的方法。

The error pretty much explains it all.

"method CreateFromDbModel does not have a translation to sql (System.NotSupportedException)"

Your CreateFromDbModel method isn't an sql function. Your application won't be able to run the CreateFromDbModel function until the objects are specifically returned to you from the server. You'll most likely have to call a ToList() or something similar on your query before you can run CreateFromDbModel on them.

杯别 2024-08-11 01:46:02

问题是因为您在 GetUsers 方法中返回 IQueryable 吗?尝试返回 List。这将强制 Linq 查询在该方法内执行。

public List<User> GetUsers(bool includeTeams)
{
    return (from u in _db.sc_Players
    where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam))
    select UserFactory2.CreateFromDbModel(u)).ToList();
}

不确定这是否能解决问题,只是预感。我能够在本地数据库上复制您在 Linqpad 中所做的事情,并且它有效。但我的示例没有返回 IQueryable。您是否在 GetUsers() 之外进一步修改 IQueryable 集合?

编辑:

我做了更多检查。仅当我修改示例时,我才能重复该错误,以便在调用 GetUsers() 后在第二个 Linq 查询中使用 IQueryable 集合:

IQueryable<User> query = GetUsers(true);

var q = from u in query
    where u.Name.Contains("Bob")
    select new {Name = u.FirstName + " " + u.LastName};

我敢打赌,如果您按照上面在 GetUsers() 中建议的方式返回一个列表,该错误就会消失。唯一的缺点是,调用 GetUsers() 后执行的任何过滤都不会限制从数据库返回的数据量,因为在调用 .ToList() 时已经执行了查询。

编辑2:

不幸的是,我认为没有其他方法可以在查询中包含工厂方法。我还有一个想法。
您可以为 IQueryable 创建一个扩展方法,将其命名为 ToUserList() 之类的名称。在 ToUserList() 内部,您可以对查询调用 ToList() 以及返回用户集合的工厂方法。使用 Linq 完成数据筛选后,调用此方法。这将允许您仅在准备好从数据库加载数据时才执行查询。下面给出一个例子。

public static List<Users> ToUserList(this IQueryable<User> query)
{
     return query.ToList().Select(u => UserFactory2.CreateFromDbModel(u)); 
}

像这样调用扩展方法:

// Filter the data using linq. When you are ready to execute the query call:
query.ToUserList(); // Query will execute and a list of User objects returned.

希望这是有道理的。
道格拉斯·H.

Is the problem becuase you are returning IQueryable in your GetUsers method? Try returning List instead. This will force the Linq query to execute within the method.

public List<User> GetUsers(bool includeTeams)
{
    return (from u in _db.sc_Players
    where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam))
    select UserFactory2.CreateFromDbModel(u)).ToList();
}

Not sure if this will fix the problem, just a hunch. I was able to duplicate what you are doing in Linqpad on a local database, and it worked. But my sample was not returning an IQueryable. Are you furthur modifing the IQueryable collection outside of GetUsers()?

Edit:

I've done some more checking. I was able to duplicate the error only when I modified my sample so the IQueryable collection was used in a second Linq query after calling GetUsers():

IQueryable<User> query = GetUsers(true);

var q = from u in query
    where u.Name.Contains("Bob")
    select new {Name = u.FirstName + " " + u.LastName};

I bet if you will return a List as suggested above in GetUsers() the error will go away. The only down side is that any filtering you do after calling GetUsers() will not limit the amount of data returned from the database because you have already executed the query when calling .ToList().

Edit 2:

Unfortunately I don’t think there is any other way to include your factory method in the query. I do have one more idea.
You can create an extension method for IQueryable, call it something like ToUserList(). Inside ToUserList() you call ToList() on the query and your factory method that returns a collection of users. Call this method when you are finished filtering the data using Linq. This will allow you to only execute the query when you are ready to load the data from the database. An example is given below.

public static List<Users> ToUserList(this IQueryable<User> query)
{
     return query.ToList().Select(u => UserFactory2.CreateFromDbModel(u)); 
}

Call the extension method like this:

// Filter the data using linq. When you are ready to execute the query call:
query.ToUserList(); // Query will execute and a list of User objects returned.

Hope this makes sense.
Douglas H.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文