Skip to content

Commit

Permalink
docs: update docs with new features
Browse files Browse the repository at this point in the history
  • Loading branch information
tolemac committed Feb 21, 2017
1 parent 84a9306 commit b1eb556
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 7 deletions.
12 changes: 6 additions & 6 deletions docs/es/extensibility-es.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ A continuación mostramos el interceptor usado para la función `MAX` de SQL. Cu
```` csharp
public class DbFunctionsMax : MethodCallInterceptorBase
{
public override Expression Intercept(MethodCallExpression m,
public override bool Intercept(MethodCallExpression m,
StringBuilder sql, Func<Expression, Expression> visit) // (1) parametros de entrada
{
if (m.Method.DeclaringType == typeof(DbFunctions)
Expand All @@ -37,10 +37,10 @@ public class DbFunctionsMax : MethodCallInterceptorBase
sql.Append($"{Dialect.Symbol(SqlSymbols.StartGroup)}"); // (4a)
visit(identifier); // (5) Procesado del identificador.
sql.Append($"{Dialect.Symbol(SqlSymbols.EndGroup)}"); // (4b)
return m; // (6) Devolvemos la misma expresión.
return true; // (6) Indicamos que hemos capturado la expresión.
}
// Si no pasa el chequeo devolvemos null para indicar que no hemos hecho nada.
return null;
// Si no pasa el chequeo devolvemos false para indicar que no hemos hecho nada.
return false;

}
}
Expand All @@ -51,15 +51,15 @@ public class DbFunctionsMax : MethodCallInterceptorBase
* El string builder donde se va añadiendo la consulta SQL. Cuando tengamos que escribir SQL lo haremos con `sql.Append()`.
* Un método para procesar expresiones, los argumentos usados en la expresión de llamada al metodo pueden ser constantes, parametros, llamadas a funciones, ...
2. Chequeo del método.
Lo primero que hacemos es comprobar que se está llamando al método que `DbFunctions.Max()`, para eso comprobamos el tipo donde está declarado el método `Method.DeclaringType` y el nombre del mismo `Method.Name`, si coinciden con `DbFunctions` y `Max` entonces procesamos, si no devolvemos null para indicar a ToleSql que siga buscando interceptores.
Lo primero que hacemos es comprobar que se está llamando al método que `DbFunctions.Max()`, para eso comprobamos el tipo donde está declarado el método `Method.DeclaringType` y el nombre del mismo `Method.Name`, si coinciden con `DbFunctions` y `Max` entonces procesamos, si no devolvemos false para indicar a ToleSql que siga buscando interceptores para esta expresión.
3. Acceso al identificador.
Sabemos que nuestra función `Max` solo acepta un parametro, así que accedemos a él mediante la expresión. Al ser una `MethodCallExpression` tiene una propiedad llamada `Arguments` que es la lista de argumentos de la función, en este caso cogemos el primero y único.
4. Escritura de literales.
Ahora lo que hacemos es escribir en SQL el literal `MAX`, en este caso lo que se hace es pedirlo al dialecto activo, usamos `Dialect.Keyword(SqlKeyword.Max)`, `Keyword` es un método del dialecto que dada una plabra clave devuelve un literal, en este caso devolverá `MAX` a no ser que usemos un dialecto para una base de datos donde no se llame así.
Acto seguido escribimos una apertura de parentesis `(`, luego pondremos el identificador y por último (4c) cerraremos el parentesis. La apertura de parentesis se realiza también mediante el dialecto, en este caso le solicitamos el simbolo `StartGroup` o `EndGroup` para cerrar: `Dialect.Symbol(SqlSymbols.StartGroup)` o `Dialect.Symbol(SqlSymbols.EndGroup)`.
5. Procesado del identificador.
El identificador puede ser otra expresión compleja, si estuvieramos seguros de que es un miembro de un parametro podríamos coger su nombre, pero como puede ser cualquier cosa la procesamos con el visitor. En este ejemplo la expresión es `DbFunctions.Max(i.TotalAmount)`, pero podría ser `DbFunctions.Max(i.Count * i.Price * 0.20)`, como ToleSql ya sabe procesar expresiones mejor lo invocamos con `visit(identifier)`.
6. Devolvemos la misma expresión que hemos procesado, de esa forma indicamos a ToleSql que no siga llamando interceptores.
6. Devolvemos `true`, de esa forma indicamos a ToleSql que no siga llamando interceptores para esta expresión.

En [/ToleSql/Expressions/Visitors/Interceptors](../../src/ToleSql/Expressions/Visitors/Interceptors) podemos ver la lista de interceptores disponibles.

Expand Down
60 changes: 59 additions & 1 deletion docs/es/modeling-es.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Modelado

### Modelado global

Algunas veces las tablas de la base de datos no se llaman como las clases de nuestros objetos, igual con los nombres de columnas e incluso podemos usar distintos esquemas donde clasificamos nuestras tablas, para ello tenemos la clase `Modeling`.

Para ello podemos hacer esto:
Expand All @@ -15,4 +17,60 @@ Modeling.Model<User>()
.SetSchema("LoB")
.SetTable("SecurityProfile")
.SetColumnName(u => u.CreatedBy, "CreatedBy_Id");
````
````

Esto establecería los valores de forma global. Siempre que se vaya a resolver el tipo `Supplier` el esquema será `WH`, siempre que se resuelva el tipo `User` se usará el esquema `LoB` y el nombre de tabla `SecurityProfile`.

También podemos establecer un esquema por defecto para todas las tablas que no tengan asociado un esquema:

```` csharp
Modeling.DefaultSchema = "dbo";
````

### Modelado por builder

Alternativamente podemos establecer configuración de modelado a nivel del propio builder.
En primer lugar un tipo se traduce en tabla usando el nombre del tipo y sin esquema, el siguiente paso es establecerle el esquema por defecto si se ha definido. Entonces se busca el tipo en el `Modeling` global y por último se buscan en el `Modeling` del builder. Por lo tanto prevalece la configuración más concreta.

Aquí unos tests que lo demuestran.

Esquema por defecto:
```` csharp
Modeling.DefaultSchema = "KKK";
var b = new SelectBuilder();
b.From<Supplier>();

var gen = b.GetSqlText();
var spec = "SELECT * FROM [KKK].[Supplier] AS [T0]";
Assert.Equal(spec, gen);
````

Esquema por defecto + modelado global:
```` csharp
Modeling.DefaultSchema = "KKK";
Modeling.Model<Supplier>().SetSchema("CUS").SetTable("CUSTOMER");
var b = new SelectBuilder();
b.From<Supplier>();

var gen = b.GetSqlText();
var spec = "SELECT * FROM [CUS].[CUSTOMER] AS [T0]";
Assert.Equal(spec, gen);
````

Esquema por defecto + modelado global + modelado por builder:
```` csharp
Modeling.ResetModeling();
Modeling.DefaultSchema = "KKK";
Modeling.Model<Supplier>().SetSchema("CUS").SetTable("CUSTOMER");

var b = new SelectBuilder();
b.Modeling.Model<Supplier>().SetSchema("dbo").SetTable("MyTable");
b.From<Supplier>();

var gen = b.GetSqlText();
var spec = "SELECT * FROM [dbo].[MyTable] AS [T0]";

Assert.Equal(spec, gen);
````

En definitiva tenemos distintos modos establecer los nombres de nuestras tablas a nuestros tipos.

0 comments on commit b1eb556

Please sign in to comment.