/// <summary>
        /// Creates the update command set with the supplied context.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="logger"></param>
        public EntityUpdateCommands(DbContext context, ILogger logger)
        {
            Context = context ?? throw new ArgumentNullException(nameof(context));
            Logger  = logger ?? throw new ArgumentNullException(nameof(logger));

            var t = typeof(TEntity);

            EntityType = Context.Model.FindEntityType(t)
                         ?? throw new ArgumentException($"The entity type {t} does not exist in the {Context.GetType()} model.");

            Key = EntityType.FindPrimaryKey()
                  ?? throw new ArgumentException($"The entity type {t} does not have a primary key in the {Context.GetType()} model.");

            var stamps = new[] { "timestamp", "rowversion" };

            EntityProperties = EntityType
                               .GetProperties()
                               .Where(x => !stamps.Contains(x.GetColumnType().ToLower()))
                               .ToArray();

            var conn = Context.Database.ProviderName;

            Knowledge = SqlKnowledge.For(conn)
                        ?? throw new ArgumentException($"The {conn} provider does not have registered SQL knowledge.");
        }
示例#2
0
        /// <summary>
        /// Creates a parameterized SQL string from the supplied query.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="logger"></param>
        public ParameterizedSql(IQueryable <TEntity> query, ILogger logger = null)
        {
            _original = query;
            _info     = new QueryInfo(query);
            DbContext = _info.Context.Context;
            _logger   = logger
                        ?? ((IInfrastructure <IServiceProvider>)DbContext)
                        .Instance
                        .GetService(typeof(ILogger <ParameterizedSql <TEntity> >)) as ILogger <ParameterizedSql <TEntity> >;

            if (DbContext.Model.FindEntityType(typeof(TEntity)) is null)
            {
                _logger?.LogInformation($"The type {typeof(TEntity)} is not part of the data model, creating read-only SQL.");
                ReadOnly = true;
            }

            _knowledge = SqlKnowledge.For(DbContext.Database.ProviderName);

            _logger?.LogDebug("Generating SQL...");

            var cmd = _info.Command;

            SqlText = cmd.CommandText;
            var paramNames = cmd.Parameters.Select(x => x.InvariantName).ToArray();

            _parameterValues = _info.Context
                               .ParameterValues
                               .Where(v => paramNames.Contains(v.Key))
                               .ToDictionary(
                v => "@" + v.Key.TrimStart('@'),
                v => v.Value
                );
            _logger?.LogDebug(SqlText);
            _logger?.LogDebug("Params: " + string.Join(", ", _parameterValues.Select(x => x.Key)));

            var rip = SelectRipper.Match(SqlText);

            if (!rip.Success)
            {
                throw new ArgumentException(
                          "The generated SQL does not match the extraction regular expression.\n" + SqlText
                          );
            }

            _action           = "SELECT";
            _fromClause       = rip.Groups["FROM"].Value.Trim();
            _whereClause      = rip.Groups["WHERE"].Value.Trim();
            IsGrouped         = !string.IsNullOrWhiteSpace(rip.Groups["GROUPBY"].Value);
            HasWithExpression = !string.IsNullOrWhiteSpace(rip.Groups["WITH"].Value);

            var sel        = rip.Groups["SELECTION"].Value.Trim();
            var aliasSplit = sel.IndexOf('.');

            if (aliasSplit <= 0)
            {
                _tableAlias = "";
            }
            else
            {
                var tbl = sel.Substring(0, aliasSplit);
                _tableAlias = _knowledge.UnquoteObjectName(tbl);
            }

            if (!ReadOnly)
            {
                if (string.IsNullOrEmpty(_tableAlias))
                {
                    _tableAlias = _info.Expression.Tables.First().Alias;
                }

                var tex = _info.Expression.Tables.FirstOrDefault(x => x.Alias == _tableAlias);
                if (tex is null)
                {
                    ReadOnly = true;
                    _logger?.LogInformation($"Failed to locate record set named {_tableAlias}.");
                }
                else if (tex is TableExpression tt)
                {
                    if (!string.IsNullOrEmpty(tt.Schema) &&
                        tt.Schema != "dbo")
                    {
                        _tableName = _knowledge.QuoteObjectName(tt.Schema) + '.' + _knowledge.QuoteObjectName(tt.Name);
                    }
                    else
                    {
                        _tableName = _knowledge.QuoteObjectName(tt.Name);
                    }
                }
                else
                {
                    ReadOnly = true;
                    _logger?.LogInformation($"Failed to locate a table expression named {_tableAlias}.");
                }
            }
        }