C# 使用Dapper.Contrib插入和多重映射
我试图做的是能够使用复杂对象进行检索和写回数据库 例如,我有两个班C# 使用Dapper.Contrib插入和多重映射,c#,sqlite,dapper,dapper-contrib,C#,Sqlite,Dapper,Dapper Contrib,我试图做的是能够使用复杂对象进行检索和写回数据库 例如,我有两个班 [Table("Children")] public class Child { public int Id { get; set; } public int ParentId { get; set; } public string Data { get; set; } } [Table("Parents")] public class Parent { public int Id { get;
[Table("Children")]
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Data { get; set; }
}
[Table("Parents")]
public class Parent
{
public int Id { get; set; }
public string Data { get; set; }
public List<Child> Children { get; set; }
public Parent()
{
Children = new List<Child>();
}
}
[表(“子项”)]
公营儿童
{
公共int Id{get;set;}
public int ParentId{get;set;}
公共字符串数据{get;set;}
}
[表(“家长”)]
公共类父类
{
公共int Id{get;set;}
公共字符串数据{get;set;}
公共列表子项{get;set;}
公共家长()
{
Children=新列表();
}
}
我使用下面的方法填充父对象
public List<Parent> GetAll()
{
var parents = new List<Parent>();
using (SQLiteConnection conn = new SQLiteConnection(sqlConnectionString))
{
string sql = $@"
SELECT * From Parents;
SELECT * FROM Children;
;";
var results = conn.QueryMultiple(sql);
parents = results.Read<Parent>().ToList();
var children = results.Read<Child>();
foreach (var parent in parents)
{
parent.Children = children.Where(a => a.ParentId == parent.Id).ToList();
}
}
return parents;
}
public List GetAll()
{
var parents=新列表();
使用(SQLiteConnection conn=newsqliteconnection(sqlConnectionString))
{
字符串sql=$@”
从家长中选择*;
从子项中选择*;
;";
var results=conn.QueryMultiple(sql);
parents=results.Read().ToList();
var children=results.Read();
foreach(父对象中的var父对象)
{
parent.Children=Children.Where(a=>a.ParentId==parent.Id).ToList();
}
}
返回父母;
}
我的问题是,既然我有了填充的对象,我想对父对象进行更改,包括添加/更新/删除Parent.Children中的值
这是我第一次使用update方法,但我认识到这里存在一些问题,例如根据子Id是否为零来确定更新或插入,以及这有点冗长
有没有办法,我是否缺少Dapper或Dapper.Contrib的一些功能,这些功能可以提供帮助方法,使这个过程更简单?
public bool Update(Parent parent)
{
bool result = true;
using (SQLiteConnection conn = new SQLiteConnection(sqlConnectionString))
{
conn.Open();
using (var tran = conn.BeginTransaction())
{
try
{
if (!conn.Update<Parent>(parent))
{
result = false;
}
foreach (var element in parent.Children)
{
if (element.Id == default(int))
{
conn.Insert<Child>(element);
}
else
{
if (!conn.Update<Child>(element))
{
result = false;
}
}
}
tran.Commit();
}
catch(Exception ex)
{
//logger.Error(ex,"error attempting update");
tran.Rollback();
throw;
}
}
}
return result;
}
公共bool更新(父级)
{
布尔结果=真;
使用(SQLiteConnection conn=newsqliteconnection(sqlConnectionString))
{
conn.Open();
使用(var tran=conn.BeginTransaction())
{
尝试
{
如果(!conn.Update(父级))
{
结果=假;
}
foreach(parent.Children中的var元素)
{
if(element.Id==默认值(int))
{
连接插件(元件);
}
其他的
{
如果(!conn.Update(元素))
{
结果=假;
}
}
}
trans.Commit();
}
捕获(例外情况除外)
{
//logger.Error(例如,“尝试更新时出错”);
事务回滚();
投掷;
}
}
}
返回结果;
}
遗憾的是,考虑到对这个问题的回答有多差,以及一般的短小精悍的问题。我决定抛弃整洁,转而使用更适合我需要的ORM。感谢所有提供建议的人。也许你只需要在已经实现这些东西的地方使用更“重”的ORM式实体框架?不幸的是,现有的需求使得实体不太可能实现,vs2017、sqlite和EF都没有发挥好,而且在很长一段时间内不太可能。你是说sqlite的EF提供程序会生成错误的查询?那奈特呢?因为“能够使用复杂对象进行检索和写回数据库”基本上就是“重型”ORM的全部内容。不,基本上是对visual studio 2017设计时安装程序的更改,导致sqlite团队至少目前放弃了对设计时组件的支持。在没有他们的情况下管理EF,在我们内部,这被认为比没有他们的情况下实施更麻烦。如果我不能用Dapper获得任何其他答案,我将调查NHibernate。至于我,不需要设计师支持。这里有代码优先,或者您可以先将数据库构建为您不喜欢代码的类的模型。另外,EF core(也可以在完整的.NET中使用)支持SQLite(虽然也没有设计器,但根本没有对EF core的设计器支持,人们仍然很乐意使用它)。对不起,我正是处于这种情况……在Dapper?Entity Framework之后,你指了什么,它也有它的挑战,在vs2017上的设置有点痛苦,但总的来说,它满足了我的需要。