Entity Framework 避免延迟加载/已经打开的 DataReader 问题

Entity Framework avoid LazyLoading / already open DataReader issue

使用连续多次运行的联合查询,如果 Users 与起始字母一起存在,我会为每个字母获得 UserlistSection 个对象。 所以我得到这样的东西:

但是查询抛出以下异常

MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first.

查询任务

public UserRepository(myDatabase database)
    {
        _database = database;
    }

public Task<ObservableCollection<User>> GetUserFriendsAsync(int id, string letter)
    {
        return Task.Factory.StartNew(() =>
        {
            try
            {
                var query1 = (from urs in _database.user_relationships
                              join u in _database.users on urs.relationship_user_from equals u.user_id
                              where urs.relationship_user_to == id
                                    && u.user_name.StartsWith(letter)
                                    && urs.relationship_status == 1
                              select new User
                              {
                                  Id = u.user_id,
                                  Username = u.user_name,
                                  AvatarByte = u.user_avatar,
                                  Gender = u.user_gender,
                                  GroupId = u.user_usergroup,
                                  LoginStatusId = u.user_loginstatus
                              });

                var query2 = (from urs in _database.user_relationships
                              join u in _database.users on urs.relationship_user_to equals u.user_id
                              where urs.relationship_user_from == id
                                    && u.user_name.StartsWith(letter)
                                    && urs.relationship_status == 1
                              select new User
                              {
                                  Id = u.user_id,
                                  Username = u.user_name,
                                  AvatarByte = u.user_avatar,
                                  Gender = u.user_gender,
                                  GroupId = u.user_usergroup,
                                  LoginStatusId = u.user_loginstatus
                              });

                // Union to get users via relationships (from - to and to - from)
                var queryUnion = query1.Union(query2).OrderBy(u => u.Username);

                return new ObservableCollection<User>(queryUnion);
            }
            catch (Exception ex)
            {
                Trace.WriteLine("UserRepository - GetUserFriendsAsync" + ex);
                return null;
            }
        });
    }

和我创建集合的对象/方法

public class UserlistSection : ObservableObject
{
    #region Attributes

    private string _letter;
    private ObservableCollection<User> _users;

    #endregion Attributes

    public string Letter
    {
        get { return _letter; }
        set { Set(ref _letter, value); }
    }

    public ObservableCollection<User> Users
    {
        get { return _users; }
        set { Set(ref _users, value); }
    }
}

// -------------------------------------------------------------------------

 public async void UpdateFriendlistCollection()
    {
        IsLoading = true;
        Friendlist = new ObservableCollection<UserlistSection>();

        for (var c = 'A'; c <= 'Z'; c++)
        {
            try
            {
                var letter = c.ToString();
                var userCollection = await _userRepository.GetUserFriendsAsync(_userObj.Id, letter);

                if (userCollection.Count < 1) return;

                foreach (var friend in userCollection)
                {
                    friend.AvatarImage = friend.GetAvatarImgByPixel(200);
                }

                var section = new UserlistSection
                {
                    Letter = letter,
                    Users = userCollection
                };

                Friendlist.Add(section);
            }
            catch (Exception ex)
            {
                Trace.WriteLine("FriendlistViewModel - UpdateFriendlistCollection: " + ex.Message);
            }
        }

        IsLoading = false;
    }

可能有更好的方法来构建查询,但我还不知道怎么做。如果有人能看到我的错误以避免延迟加载/解决异常,那就太好了。

如果我遗漏了一些解释,请告诉我。

编辑

当我这样添加MultipleActiveResultSets=True时,它告诉我不支持关键字?

<connectionStrings>
<add name="someDatabase"   connectionString="metadata=res://*/Repository.Database.SomeDatabase.csdl|res://*/Repository.Database.SomeDatabase.ssdl|res://*/Repository.Database.SomeDatabase.msl;provider=MySql.Data.MySqlClient;provider connection string=&quot;server=127.0.0.1;user id=someUser;persistsecurityinfo=True;password=somePassword;multipleactiveresultsets=True;database=someDatabase;&quot;" providerName="System.Data.EntityClient" />

System.ArgumentException: Keyword not supported.
Parametername: multipleactiveresultsets
bei MySql.Data.MySqlClient.MySqlConnectionStringBuilder.GetOption(String key)
bei MySql.Data.MySqlClient.MySqlConnectionStringBuilder.set_Item(String  keyword, Object value)

您应该在配置的连接字符串中启用 MARS。

"MultipleActiveResultSets=True" 添加到连接字符串。

更多info.

编辑

来自 MSDN

When you call the Load method during a foreach (C#) or For Each (Visual Basic) enumeration, the Entity Framework tries to open a new data reader. This operation will fail unless you have enabled multiple active results sets by specifying multipleactiveresultsets=true in the connection string. For more information, see Using Multiple Active Result Sets (MARS) on MSDN. You can also load the result of the query into a List collection, which closes the data reader and enables you to enumerate over the collection to load referenced entities

编辑

对于 MySQL 我找到了 this。也许对你有帮助。

好像MySQL不支持MARS。如果你可以为 MS SQL Server Express 更改数据库。或者更改 ORM,例如 NHibernate。