Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DbContext SqlQuery返回意外结果_C#_Sql_Entity Framework_Code First_Dbcontext - Fatal编程技术网

C# DbContext SqlQuery返回意外结果

C# DbContext SqlQuery返回意外结果,c#,sql,entity-framework,code-first,dbcontext,C#,Sql,Entity Framework,Code First,Dbcontext,我有两个实体类User和Connection,User有一个Connection集合 它返回一个连接列表为空的用户对象,而不是用数据库返回的数据填充连接。 我尝试过用内部联接替换交叉联接,但结果仍然相同 我不知道如何修改sql查询以返回实际数据。我如何才能做到这一点,或者我缺少什么?要做到这一点,我首先检索/检查用户是否存在,然后检索他们的连接并将其添加到该用户的连接列表中 public User GetUserAndConnections(string username, string roo

我有两个实体类User和Connection,User有一个Connection集合

它返回一个连接列表为空的用户对象,而不是用数据库返回的数据填充连接。 我尝试过用内部联接替换交叉联接,但结果仍然相同


我不知道如何修改sql查询以返回实际数据。我如何才能做到这一点,或者我缺少什么?

要做到这一点,我首先检索/检查用户是否存在,然后检索他们的连接并将其添加到该用户的连接列表中

public User GetUserAndConnections(string username, string roomname)
{
    var user = _context.Users.Find(username);
    if (user != null)
    {
        var connections =
            _context.Users.Where(u => u.UserName == username)
                .SelectMany(x => x.Connections.Where(p => p.RoomName == roomName))
                .ToList();
        user.AddExistingConnections(connections);
    }

    return user;
}

因为您在这里没有做任何特殊的事情,所以甚至没有任何投影,您可以直接从上下文返回实体,包括您想要的导航属性:

e、 g.鉴于这些实体:

class User
{
    public string username { get; set; }
    public ICollection<Connection> Connections { get; set; }
}

class Connection
{
    public string ConnectionId { get; set; }
    public string RoomName { get; set; }
}
不要忘记延迟执行——如果您不知道延迟执行是什么,也不知道查询是如何在EF中构建的,那么就值得查找它——一般的经验法则是;对数据库的查询越少,在C语言中对数据库风格操作(如聚合)的处理越少,应用程序执行的速度就越快-因此,请确保在完全构建查询之前,不要枚举结果,或者在.NET端使用LINQ to对象执行所有数字处理,不是在SQL中它应该在哪里

因此,调用.ToList或枚举上述查询将得到结果

EF将使用您选择的提供程序System.Data.SqlClient将您所做的任何事情转换为正确的SQL方言。您不需要编写任何SQL

您可能执行的其他一些查询示例:

// Get me users called Fred including their connection details
context.Users.Include(x => x.Connections).Where(u => u.Username == "Fred")

 // Get me users that are currently connected to "Game Room"
context.Users.Include(x => x.Connections).Where(u => u.Connections.Any(c => c.RoomName == "Game Room")
所有这些都不需要您编写任何SQL—在运行这些查询时放置一个SQL跟踪,以查看EF的功能,通常它编写查询的效果会比您以往任何时候都好:只是有时候不需要,而且通常是在您做一些愚蠢的事情时

编辑

好的,我看到您正在尝试过滤用户和通过连接返回的连接,在这种情况下,您需要将导航属性作为单独的查询显式加载,或者使用投影进行过滤

e、 g

显式加载

这确实会导致两个查询

投影

这将生成一个匿名类型,其中包含用户属性和连接属性。如果需要通过某种域边界发送,也可以将其投影到已知类型


这将是针对数据源的单个查询

我认为除非使用延迟加载,否则不能使用SqlQuery返回子对象。我认为可以通过某种方式修改sql查询,以实现完美的转换,可能是子查询之类的。您使用SqlQuery方法而不是仅使用直接用linq?@MattyM查询用户实体我试图获取用户到特定房间的连接列表正如DavidG和Matty所说,原始SQL不允许包含相关实体,因此,您需要使用linq来获取用户实体,并使用include来填充connections集合?你为什么要交叉加入?交叉联接为左表中的每一行返回右表中的一行。你想要一个左连接,但实际上你不想要一个连接,你想要实体框架来为你做这件事,你基本上错过了ORM在针对数据源编写简单的非特定于提供程序的SQL时的全部要点。使用context.Users.Includex=>x可以得到相同的结果。Connections@Charleh你能举个例子吗。您甚至可以编辑answer@Charleh我用linq重新编写了它。我的目的是检索用户与房间的连接列表。在我的场景中,用户可以从不同的设备连接到房间,并且将为房间创建一个新连接并映射到该用户。我想检索用户及其到该房间的连接详细信息,为此,我使用上面的linq查询。我可以用一个查询来检索用户和与房间的连接吗?是的,我发布的查询正好提供了-context.Users.Includex=>x.connections-它检索所有用户及其连接,以筛选特定用户使用的context.Users.Includex=>x.connections.Whereu=>u.UserName==UserName。如果您想让某个特定房间中的任何用户使用它的context.users.Includex=>x.Connections.Whereu=>u.Connections.Anyc=>c.RoomName==RoomName—您可以从中获得任何您想要的内容,而无需投影。如果您想展平数据、修改数据或聚合数据以及其他一些用途,则只需进行投影。我正在使用显式加载方法,因为它会返回用户和连接,投影样式返回一个用户和连接列表,您必须将这些用户和连接投影/转换为所需的类型。如果需要,您可以在投影期间重新创建该类型
您希望不创建匿名类型,除非您对多个查询的小性能损失感到满意,而且可能会非常小。我在LinqPad上测试了这两个查询,带有投影的查询返回了IEnumerable和IEnumerable。用户集合的连接列表填充了正确的值,并且连接列表具有相同的连接。如果我投影到一个命名类型,它必须是一个具有IEnumerable和IEnumerable属性的a类型,然后选择返回用户及其关联连接的第一个元素type.Users.FirstOrDefault。我猜显式加载对性能的影响很小,或者我可以使用投影?
class User
{
    public string username { get; set; }
    public ICollection<Connection> Connections { get; set; }
}

class Connection
{
    public string ConnectionId { get; set; }
    public string RoomName { get; set; }
}
using(YourDbContext context = new YourDbContext())
{
    var query = context.Users.Include(user => user.Connections);

    // Do stuff with query
}
// Get me users called Fred including their connection details
context.Users.Include(x => x.Connections).Where(u => u.Username == "Fred")

 // Get me users that are currently connected to "Game Room"
context.Users.Include(x => x.Connections).Where(u => u.Connections.Any(c => c.RoomName == "Game Room")
var user = context.Users.First(x => x.UserName == username);

context.Entry(user).Collection(x => x.Connections).Query().Where(x => x.RoomName == roomName).Load();
var usersConnections = context.Users
.Where(u => u.UserName == userName)
.Select(u => new
{
    User = u,
    Connections = u.Connections.Where(c => c.RoomName == roomName)
});