Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.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# 简洁的一对多关系_C#_Asp.net Mvc_Asp.net Core_Asp.net Core Mvc_Dapper - Fatal编程技术网

C# 简洁的一对多关系

C# 简洁的一对多关系,c#,asp.net-mvc,asp.net-core,asp.net-core-mvc,dapper,C#,Asp.net Mvc,Asp.net Core,Asp.net Core Mvc,Dapper,我有3个表,结构如下: CREATE TABLE [User]( Id int NOT NULL, Name varchar(50) PRIMARY KEY (Id) ) CREATE TABLE [Role]( Id int NOT NULL, UserId int NOT NULL, Name varchar(50), PRIMARY KEY (Id), FOREIGN KEY (UserId) REFERENCES [Use

我有3个表,结构如下:

CREATE TABLE [User](
    Id int NOT NULL,
    Name varchar(50)
    PRIMARY KEY (Id)
)

CREATE TABLE [Role](
    Id int NOT NULL,
    UserId int NOT NULL,
    Name varchar(50),
    PRIMARY KEY (Id),
    FOREIGN KEY (UserId) REFERENCES [User](Id)
)


CREATE TABLE [Description](
    Id int NOT NULL,
    RoleId int NOT NULL,
    Name varchar(50)
    FOREIGN KEY (RoleId) REFERENCES [Role](Id)
)
正如您所看到的,它是嵌套两次的一对多关系。在代码中,我有以下类来表示它们:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }

    public IEnumerable<Role> Roles { get; set; }
}

public class Role
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string Name { get; set; }

    public IEnumerable<Description> Descriptions { get; set; }
}

public class Description
{
    public int Id { get; set; }
    public int RoleId { get; set; }
    public string Name { get; set; }
}
然后我像这样处理它:

var queryFour = "SELECT u.Id as 'UserId', u.Name as 'UserName', r.Id as 'RoleId', r.Name as 'RoleName', d.Id as 'DescriptionId', d.Name as 'DescriptionName' FROM  [User] u INNER JOIN [Role] r ON u.Id = r.UserId INNER JOIN [Description] d ON r.Id = d.RoleId WHERE u.Id = 1";

var conn = new SqlConnection();
using (var con = conn)
{
    var myUser = new User();
    var result = con.Query<Combination>(queryFour);
    if (result != null)
    {
        var user = result.FirstOrDefault();
        myUser.Id = user.UserId;
        myUser.Name = user.UserName;
        var roles = result.GroupBy(x => x.RoleId).Select(x => x.FirstOrDefault());
        var myRoles = new List<Role>();
        if (roles != null)
        {
            foreach (var role in roles)
            {
                var myRole = new Role
                {
                    Id = role.RoleId,
                    Name = role.RoleName
                };

                var descriptions = result.Where(x => x.RoleId == myRole.Id);
                var descList = new List<Description>();
                foreach (var description in descriptions)
                {
                    var desc = new Description
                    {
                        Id = description.DescriptionId,
                        RoleId = description.RoleId,
                        Name = description.DescriptionName
                    };
                    descList.Add(desc);
                }
                myRole.Descriptions = descList;
                myRoles.Add(myRole);
            }
        }
        myUser.Roles = myRoles;
    }

    Console.WriteLine("User: " + myUser.Name);
    foreach (var myUserRole in myUser.Roles)
    {
        Console.WriteLine("Role: " + myUserRole.Name);
        foreach (var description in myUserRole.Descriptions)
        {
            Console.WriteLine("Description: " + description.Name);
        }
    }
}
public static void Main(String[] args)
{
    int roleID = 6;

    UserDataAccess dataAccess = new UserDataAccess();
    IEnumerable<User> usersInRole = dataAccess.GetUsersByRoleID(roleID);

    DisplayManager displayManager = new DisplayManager(usersInRole);
    displayManager.DisplayInfo();
}
var queryFour=“选择u.Id作为‘UserId’,u.Name作为‘UserName’,r.Id作为‘RoleId’,r.Name作为‘RoleName’,d.Id作为‘DescriptionId’,d.Name作为‘DescriptionName’,从[User]u内部联接[Role]r上选择u.Id=r.UserId内部联接[Description]d上选择r.Id=d.RoleId,其中u.Id=1”;
var conn=new SqlConnection();
使用(var con=conn)
{
var myUser=新用户();
var result=con.Query(queryFour);
如果(结果!=null)
{
var user=result.FirstOrDefault();
myUser.Id=user.UserId;
myUser.Name=user.UserName;
var roles=result.GroupBy(x=>x.RoleId);
var myRoles=新列表();
if(角色!=null)
{
foreach(角色中的var角色)
{
var myRole=新角色
{
Id=role.RoleId,
Name=role.RoleName
};
var descriptions=result.Where(x=>x.RoleId==myRole.Id);
var descList=新列表();
foreach(描述中的变量描述)
{
var desc=新描述
{
Id=description.DescriptionId,
RoleId=description.RoleId,
Name=description.DescriptionName
};
描述列表。添加(描述);
}
myRole.Descriptions=descList;
添加(myRole);
}
}
myUser.Roles=myRoles;
}
Console.WriteLine(“用户:+myUser.Name”);
foreach(myUser.Roles中的var myUserRole)
{
Console.WriteLine(“角色:+myUserRole.Name”);
foreach(myUserRole.Descriptions中的变量描述)
{
Console.WriteLine(“Description:+Description.Name”);
}
}
}
两个方法中的结果输出相同,第二个方法使用1个查询,而不是3个查询

编辑2:需要考虑的是,我对这3个表的数据经常更新。

编辑3:

private static void SqlTest()
{
    using (IDbConnection connection = new SqlConnection())
    {
        var queryOne = "SELECT Id FROM [TestTable] With(nolock) WHERE Id = 1";
        var queryTwo = "SELECT B.Id, B.TestTableId FROM [TestTable] A With(nolock) INNER JOIN [TestTable2] B With(nolock) ON A.Id = B.TestTableId WHERE A.Id = 1";
        var queryThree = "SELECT C.Id, C.TestTable2Id FROM [TestTable3] C With(nolock) INNER JOIN [TestTable2] B With(nolock) ON B.Id = C.TestTable2Id INNER JOIN [TestTable] A With(nolock) ON A.Id = B.TestTableId WHERE A.Id = 1";

            var gridReader = connection.QueryMultiple(queryOne + " " + queryTwo + " " + queryThree);
            var user = gridReader.Read<Class1>().FirstOrDefault();

            var roles = gridReader.Read<Class2>().ToList();

            var descriptions = gridReader.Read<Class3>().ToLookup(d => d.Id);

            user.Roles= roles;

            user.Roles.ForEach(r => r.Properties = descriptions[r.Id].ToList());
    }
}
private static void SqlTest()
{
使用(IDbConnection connection=newSQLConnection())
{
var queryOne=“使用(nolock)从[TestTable]中选择Id,其中Id=1”;
var queryTwo=“从[TestTable]A中选择B.Id,B.TestTableId,并在A.Id=B.TestTableId中使用(nolock)内部连接[TestTable2]B和(nolock)”,其中A.Id=1”;
var querytree=“从[TestTable3]C中选择C.Id,C.TestTable2Id,并在B上使用(nolock)内部连接[TestTable2]B和(nolock)。Id=C.TestTable2Id内部连接[TestTable]A和(nolock)在A.Id=B.TestTableId,其中A.Id=1”;
var gridReader=connection.QueryMultiple(queryOne+“”+queryTwo+“”+queryTree);
var user=gridReader.Read().FirstOrDefault();
var roles=gridReader.Read().ToList();
var descriptions=gridReader.Read().ToLookup(d=>d.Id);
user.Roles=角色;
user.Roles.ForEach(r=>r.Properties=descriptions[r.Id].ToList());
}
}
另一种方法(使用.Net核心处理代码片段):

  • 为什么不创建这样的数据库视图-
  • 创建视图myview 作为 选择u.Id为“UserId”,u.Name为“UserName”,r.Id为“RoleId”, r、 名称为“RoleName”,d.Id为“DescriptionId”,d.Name为“DescriptionName” 从用户u内部加入角色r ON u.Id=r.UserId r.Id=d.RoleId上的内部联接描述d

  • 然后,您可以使用cleaner查询,如下所示:

        public List<Combination> GetData(int userId)
        {
            String query = "select * from myview" + " where userId = " + userId + ";";
    
            using (System.Data.Common.DbConnection _Connection = database.Connection)
            {
                _Connection.Open();
                return _Connection.Query<Combination>(query).ToList();
            }
        }
    
    public List GetData(int userId)
    {
    String query=“从myview”+”中选择*,其中userId=“+userId+”;”;
    使用(System.Data.Common.DbConnection _Connection=database.Connection)
    {
    _Connection.Open();
    return_Connection.Query(Query.ToList();
    }
    }
    
  • 您的处理代码如下所示:

  • [注意:这可以进一步增强。]

            public static void process (List<Combination> list)
            {
                User myUser = new User(); myUser.Id = list[0].UserId; myUser.Name = list[0].UserName;
                var myroles = new List<Role>(); var r = new Role(); string currentRole = list[0].RoleName;
                var descList = new List<Description>(); var d = new Description();
    
                // All stuff done in a single loop.
                foreach (var v in list)
                {
                    d = new Description() { Id = v.DescriptionId, RoleId = v.RoleId, Name = v.DescriptionName };
                    if (currentRole == v.RoleName)
                    {
                        r = new Role() { Id = v.RoleId, Name = v.RoleName, UserId = v.UserId, Descriptions = descList };                    
                        descList.Add(d);
                    }
                    else
                    {
                        myroles.Add(r);
                        descList = new List<Description>(); descList.Add(d);
                        currentRole = v.RoleName;
                    }
                }
                myroles.Add(r);
                myUser.Roles = myroles;
    
                Console.WriteLine("User: " + myUser.Name);
                foreach (var myUserRole in myUser.Roles)
                {
                    Console.WriteLine("Role: " + myUserRole.Name);
                    foreach (var description in myUserRole.Descriptions)
                    {
                        Console.WriteLine("Description: " + description.Name);
                    }
                }
            }
    
    公共静态作废流程(列表)
    {
    用户myUser=new User();myUser.Id=list[0]。用户Id;myUser.Name=list[0]。用户名;
    var myroles=new List();var r=new Role();string currentRole=List[0]。RoleName;
    var descList=new List();var d=new Description();
    //所有的事情都在一个循环中完成。
    foreach(列表中的var v)
    {
    d=新描述(){Id=v.DescriptionId,RoleId=v.RoleId,Name=v.DescriptionName};
    if(currentRole==v.RoleName)
    {
    r=newrole(){Id=v.RoleId,Name=v.RoleName,UserId=v.UserId,Descriptions=descList};
    增加(d);
    }
    其他的
    {
    添加(r);
    descList=new List();descList.Add(d);
    currentRole=v.RoleName;
    }
    }
    添加(r);
    myUser.Roles=myroles;
    Console.WriteLine(“用户:+myUser.Name”);
    foreach(myUser.Roles中的var myUserRole)
    {
    Console.WriteLine(“角色:+myUserRole.Name”);
    foreach(myUserRole.Descriptions中的变量描述)
    {
    Console.WriteLine(“Description:+Description.Name”);
    }
    }
    }
    
    从性能的角度来看,内部联接比其他形式的查询(如子查询、相关子查询等)更好。但归根结底,一切都归结为SQL执行计划。

    您的第一个选择是
            public static void process (List<Combination> list)
            {
                User myUser = new User(); myUser.Id = list[0].UserId; myUser.Name = list[0].UserName;
                var myroles = new List<Role>(); var r = new Role(); string currentRole = list[0].RoleName;
                var descList = new List<Description>(); var d = new Description();
    
                // All stuff done in a single loop.
                foreach (var v in list)
                {
                    d = new Description() { Id = v.DescriptionId, RoleId = v.RoleId, Name = v.DescriptionName };
                    if (currentRole == v.RoleName)
                    {
                        r = new Role() { Id = v.RoleId, Name = v.RoleName, UserId = v.UserId, Descriptions = descList };                    
                        descList.Add(d);
                    }
                    else
                    {
                        myroles.Add(r);
                        descList = new List<Description>(); descList.Add(d);
                        currentRole = v.RoleName;
                    }
                }
                myroles.Add(r);
                myUser.Roles = myroles;
    
                Console.WriteLine("User: " + myUser.Name);
                foreach (var myUserRole in myUser.Roles)
                {
                    Console.WriteLine("Role: " + myUserRole.Name);
                    foreach (var description in myUserRole.Descriptions)
                    {
                        Console.WriteLine("Description: " + description.Name);
                    }
                }
            }
    
    var queryOne = "SELECT Id, Name FROM [User] WHERE Id = 1";
    var queryTwo = "SELECT r.Id, r.UserId, r.Name FROM  [User] u INNER JOIN [Role] r ON u.Id = r.UserId WHERE u.Id = 1";
    var queryThree = "SELECT d.Id, d.RoleId, d.Name FROM  [User] u INNER JOIN [Role] r ON u.Id = r.UserId INNER JOIN [Description] d ON r.Id = d.RoleId WHERE u.Id = 1";
    
    var conn = new SqlConnection();
    
    using (var con = conn)
    {
        var gridReader = con.QueryMultiple(queryOne + " " + queryTwo + " " + queryThree);
        var user = gridReader.Read<User>().FirstOrDefault();
        if (user == null)
        {
            return;
        }
    
        var roles = gridReader.Read<Role>().ToList();
        var descriptions = gridReader.Read<Description>().ToLookup(d => d.RoleId);
    
        user.Roles = roles;
        roles.ForEach(r => r.Descriptions = descriptions[r.Id]);
    }
    
    public static void Main(String[] args)
    {
        int roleID = 6;
    
        UserDataAccess dataAccess = new UserDataAccess();
        IEnumerable<User> usersInRole = dataAccess.GetUsersByRoleID(roleID);
    
        DisplayManager displayManager = new DisplayManager(usersInRole);
        displayManager.DisplayInfo();
    }