【问题标题】:LINQ 2 DB insert dynamic into tableLINQ 2 DB 动态插入表
【发布时间】:2020-09-17 08:13:17
【问题描述】:

我想使用动态以便能够选择要定义的列以及我想让数据库设置DEFAULT 值的列。 有没有办法将dynamic 插入表中并返回Id

我在 DataConnectionITable<> 上尝试了各种重载,但我唯一能实现的结果是获取受影响的行数。

这是我的代码:

人员表架构

CREATE TABLE [dbo].[Person] (
    [Id]        BIGINT       IDENTITY (1, 1) NOT NULL,
    [Name]      VARCHAR (50) NOT NULL,
    [Surname]   VARCHAR (50) NOT NULL,
    [BirthDate] DATE         DEFAULT (getdate()) NOT NULL
);

.NET Core 控制台应用程序

public class Person
{
    public uint Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public DateTime BirthDate { get; set; }
}
public class PeopleDataConnection : DataConnection
{
    public PeopleDataConnection(string connectionString)
        : base(ProviderName.SqlServer, connectionString)
    { }

    public ITable<Person> People => this.GetTable<Person>();
}
class Program
{
    static async Task Main(string[] args)
    {
        await using (var db = new PeopleDataConnection("Server=DESKTOP-I41VSUN;integrated Security=SSPI;Database=MotoGPRiders;"))
        {
            var dynamicPerson = new { Name = "Cal", Surname = "Crutchlow", BirthDate = new DateTime(1985, 10, 29) };
            var person_without_id = new Person { Name = "Valentino", Surname = "Rossi", BirthDate = new DateTime(1979, 2, 16) };

            var affectedRowsCount = await db.InsertAsync(dynamicPerson, nameof(Person));
            affectedRowsCount = await db.People
                .Value(x => x.Name, person_without_id.Name)
                .Value(x => x.Surname, person_without_id.Surname)
                .Value(x => x.BirthDate, person_without_id.BirthDate)
                .InsertAsync();
        }
        Console.ReadLine();
    }
}

第一个插入完成工作但不能返回Id,第二个让我选择列但不是动态的。

有没有办法做到这一点? 提前致谢!

【问题讨论】:

    标签: .net orm repository linq2db


    【解决方案1】:

    您可以通过InsertWithInt64IdentityAsync 函数检索身份值。这种插入有很多重载:

    var insertedId = await db.People
                .Value(x => x.Name, person_without_id.Name)
                .Value(x => x.Surname, person_without_id.Surname)
                .Value(x => x.BirthDate, person_without_id.BirthDate)
                .InsertWithInt64IdentityAsync();
    

    您还可以过滤掉必须通过具有columnFilter 参数的重载插入的属性:

    var insertedId = await db.InsertAsync(person, 
        e => e.MemberName.In("Name", "Surname", "BirthDate"));
    

    对于具有匿名类的变体,您必须创建自己的函数,该函数使用 Value.Value.Value + InsertWithInt64IdentityAsync 调用通过反射生成调用:

    public static class DynamicExtensions
    {
        public static IValueInsertable<T> GenerateInsertable<T>(this ITable<T> table, object obj)
        {
            var dynamicAccessor = TypeAccessor.GetAccessor(obj.GetType());
            var accessor = TypeAccessor.GetAccessor<T>();
            var objValue = Expression.Constant(obj);
            IValueInsertable<T> insertable = null;
            foreach (var dynamicMember in dynamicAccessor.Members)
            {
                var found = accessor.Members.Find(m => m.Name == dynamicMember.Name);
                if (found == null)
                    continue;
                var sourceParam = Expression.Parameter(typeof(T), "e");
                var property = Expression.Lambda(Expression.MakeMemberAccess(sourceParam, found.MemberInfo),
                    sourceParam);
                Expression value = Expression.MakeMemberAccess(objValue, dynamicMember.MemberInfo);
                if (value.Type != found.Type)
                    value = Expression.Convert(value, found.Type);
                value = Expression.Lambda(value);
    
                if (insertable == null)
                {
                    var method = Methods.LinqToDB.Insert.T.ValueExpression.MakeGenericMethod(typeof(T), found.Type);
                    insertable = (IValueInsertable<T>)method.Invoke(null, new object[] { table, property, value });
                }
                else
                {
                    var method = Methods.LinqToDB.Insert.VI.ValueExpression.MakeGenericMethod(typeof(T), found.Type);
                    insertable = (IValueInsertable<T>)method.Invoke(null, new object[] { insertable, property, value });
                }
            }
    
            return insertable;
        }
    
        public static long? InsertWithIdentityDynamic<T>(this ITable<T> table, object obj)
        {
            var insertable = GenerateInsertable(table, obj);
            if (insertable == null)
                return null;
            
            return insertable.InsertWithInt64Identity();
        }
    
        public static async Task<long?> InsertWithIdentityDynamicAsync<T>(this ITable<T> table, object obj, CancellationToken cancellationToken = default)
        {
            var insertable = GenerateInsertable(table, obj);
            if (insertable == null)
                return null;
    
            return await insertable.InsertWithInt64IdentityAsync(cancellationToken);
        }
    }
    

    及用法:

    var insertedId = await db.GetTable<Person>()
        .InsertWithIdentityDynamicAsync(dynamicPerson);
            
           
    

    【讨论】:

      猜你喜欢
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      • 2011-04-10
      • 2019-10-19
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      相关资源
      最近更新 更多