private static CommandInfo InitCommand(DapperAccessLayer layer, MethodInfo method) { CommandAttribute attr = method.GetCustomAttributes(typeof(CommandAttribute), false).Cast <CommandAttribute>().Single(); CommandInfo info = new CommandInfo() { Attribute = attr, TimeoutSeconds = attr.CommandTimeout > 0 ? attr.CommandTimeout : (int?)null }; // Find all method parameters that shall be wrapped by runtime DTO type PropertyDefinition[] properties = method.GetParameters() .Where(p => IsDatabaseType(p.ParameterType)) .Select(p => new PropertyDefinition(p.Name, p.ParameterType)) .ToArray(); // If any, create runtime dto type if (properties.Length > 0) { // First create an interface definining the properties string interfaceTypeName = method.DeclaringType.FullName.Replace('+', '_') + "." + method.Name + "_" + method.GetHashCode().ToString(); Type interfaceType = s_Factory.Module.Assembly.GetType(interfaceTypeName); if (interfaceType == null) { interfaceType = s_Factory.Module.DefineInterface(interfaceTypeName, null, properties); } // Then implement that by runtime dto type info.ParameterType = s_ParameterFactory.Implement(interfaceType); info.ParameterTypeProperties = info.ParameterType.GetProperties(); } return(info); }
protected static object ExecNonQuery(DapperAccessLayer layer, CommandInfo info, object[] parameters) { // Define how to execute on open connection Func <IDbConnection, object, object> exec = (connection, parameter) => { // Let Dapper do the hard work return(connection.Execute(info.Attribute.CommandText, parameter, null, info.TimeoutSeconds, info.Attribute.CommandType)); }; return(ExecCommand(layer, info, parameters, exec)); }
/// <summary> /// Called once for each interface method when runtime class instance is created. /// </summary> /// <param name="layer"></param> /// <param name="method"></param> /// <returns></returns> protected static CommandInfo InitQuery(DapperAccessLayer layer, MethodInfo method) { CommandInfo info = InitCommand(layer, method); // Extract row type from signature and create specialized execute method Type rowType = method.ReturnType.GetGenericArguments().Single(); MethodInfo execMethod = s_ExecCommandMethod.MakeGenericMethod(rowType); info.ExecQuery = (Func <DapperAccessLayer, CommandInfo, object[], object>)Delegate.CreateDelegate(typeof(Func <DapperAccessLayer, CommandInfo, object[], object>), execMethod); return(info); }
private static object ExecQueryGeneric <T>(DapperAccessLayer layer, CommandInfo info, object[] parameters) { // See if we shall read lazy or not bool buffered = ((QueryAttribute)info.Attribute).Buffered; // Define how to execute on open connection Func <IDbConnection, object, object> exec = (connection, parameter) => { // Let Dapper do the hard work return(connection.Query <T>(info.Attribute.CommandText, parameter, buffered: buffered, commandType: info.Attribute.CommandType, commandTimeout: info.TimeoutSeconds)); }; return(ExecCommand(layer, info, parameters, exec)); }
private static object ExecCommand(DapperAccessLayer layer, CommandInfo info, object[] parameters, Func <IDbConnection, object, object> command) { // Make sure we have an open connection IDbConnection con = layer._connectionFactory(); bool close = con.State != ConnectionState.Open; if (close) { con.Open(); } try { // Default is to use DTO provided as single param to interface method (the Dapper style) object parameter = parameters.FirstOrDefault(); // If we're using runtime dto type, create instance of it and set properties from method parameters if (info.ParameterType != null) { parameter = Activator.CreateInstance(info.ParameterType); for (int i = 0; i < info.ParameterTypeProperties.Length; i++) { info.ParameterTypeProperties[i].SetValue(parameter, parameters[i], null); } } return(command(con, parameter)); } finally { if (close) { con.Close(); } } }
protected static CommandInfo InitNonQuery(DapperAccessLayer layer, MethodInfo method) { return(InitCommand(layer, method)); }
/// <summary> /// Called whenever interface method is executed. /// </summary> /// <param name="layer"></param> /// <param name="info"></param> /// <param name="parameters"></param> /// <returns></returns> protected static object ExecQuery(DapperAccessLayer layer, CommandInfo info, object[] parameters) { // Execute in specialized generic method to be able to call Dapper query return(info.ExecQuery(layer, info, parameters)); }