Eduardo Quintás - SABIA

Transcripción

Eduardo Quintás - SABIA
Eduardo Quintás
Guía
•
•
•
•
•
•
Novedades en C# 3.0
30
Fundamentos de LINQ
Linq To Objects
Linq To XML
Li To
Linq
T Entities
E titi
Recursos
Lenguaje Integrado de Consultas: LINQ
Evolución de .NET
2002
2003
2005
2006
2007
2010
Herramienta
(Visual
Studio)
VS 2002
VS 2003
VS2005
VS200
VS2005
VS2008
VS2010
Lenguaje
C# v1.0
VB.NET
(v7.0)
C# v1.1
VB.NET
(v7.1)
C# v2.0
VB2005
(v8.0)
como
antes
C# v3.0
VB9
(v9.0)
C# 4.0
VB10
(v10.0)
Librerías
Lib
í
Framework
NetFx v1.0
NetFx v1.1
NetFx v2.0
NetFx
v3.0
NetFx
v3.5
NetFx
V4.0
Engine
g e
(CLR)
CLR v1.0
CLR v1.1
CLR v2.0
como
antes
como
antes
CLR v4.0
+ Extensiones
C# 3.0 - Objetivos
I
Integrar
objetos,
bj
d
datos
relacionales
l i
l y XML
Y:
Hacer el lenguaje más conciso
Añadir constructores de programación funcional
No ligar el lenguaje a APIs específicas
Mantenerse 100% compatible hacia atrás
Resultado:
• Métodos extensores
extensores, tipos anónimos
anónimos,
constructores sin parámetros, inferencia de
tipos expresiones lambda,
tipos,
lambda árboles de expresión
• Más un p
poquito
q
de azucar sintáctico …
from p in Passengers
where p.Citizenship == “ES”
select new { p.Id
p
p.Id,
Id, p.Name
p Name };
Nuevas características
•
•
•
•
•
•
•
Inicializadores de objetos
Inferencia de tipos
Ti
Tipos
anónimos
ó i
Métodos extensores
Expresiones
i
lambda
l bd
Árboles de expresión
LINQ!!!
Inicializadores de Objetos
public class Passenger
{
public string Id {get; set;}
public string Name {get; set;}
public DateTime BirthDate {get; set;}
}
public Passenger(string id, string name,
DateTime birthDate) // OPCIONAL!!!!
{
Id=id; Name=name; BirthDate = birthDate;
}
Asignación
A
i
ió de
d
Campos o
Propiedades
Passenger p = new Passenger () { Id = “A4”, Name = “Cabezabolo, Manolo” };
Passenger p = new Passenger();
p.Id = “A4”;
A4 ;
p.Name = “Cabezabolo, Manolo”;
Inferencia
f
i de
d Tipos
i
int i = 666;
string s = “Hola";
double d = 3.14;
int[] numbers = new int[] {1, 2, 3};
Dictionary<int,Pedido> pedidos = new Dictionary<int,Pedido>();
var
var
var
var
var
i = 666;
s = “Hola";
d = 3.14;
numbers = new int[] {1, 2, 3};
pedidos = new Dictionary<int,Pedido>();
p
y
,
()
“El tipo en el lado de
la derecha”
Tipos Anónimos
class XXX
{
public string Name;
public
bli int
i t Age;
A
}
XXX
var o = new { Name = “Pantoja”, Age= 75 };
Métodos Extensores
Método extensor
namespace MisCosas
{
public static class Extensiones
{
public static string Concatenar(this IEnumerable<string> strings
strings,
string separador) {…}
}
}
using MisCosas;
Incluir extensiones en el ámbito
string[] nombres = new string[] { “Edu", “Juan", “Manolo" };
string s = nombres.Concatenar(",
(
");
)
IntelliSense!
obj.Foo(x, y)

XXX.Foo(obj, x, y)
Expresiones Lambda
Delegado
genérico
public delegate bool Predicate<T>(T obj);
public
bli class
l
Li
List<T>
t<T>
{
public List<T> FindAll(Predicate<T> test) {
List<T> result = new List<T>();
foreach (T item in this)
if (test(item)) result.Add(item);
return result;
}
…
}
Tipo
Ti
genérico
Expresiones Lambda
public class MiClase
{
public static void Main() {
List<Cliente> clientes = ObtenerListaClientes();
List<Cliente> locales =
clientes FindAll(
clientes.FindAll(
new Predicate<Cliente>(CiudadIgualCoruna)
);
}
static bool CiudadIgualCoruna(Cliente c) {
return c.Ciudad == “A Coruña";
}
}
Expresiones Lambda
p
public
class MiClase
{
public static void Main() {
List<Cliente> clientes = ObtenerListaClientes ();
List<Cliente> locales =
clientes.FindAll(
li t
Fi dAll(
delegate(Cliente c) { return c.Ciudad == “A Coruña"; }
);
}
}
Delegado
Anónimo
ó i
Expresiones Lambda
public class MiClase
{
public static void Main() {
List<Cliente> clientes = ObtenerListaClientes ();
List<Cliente> locales =
clientes.FindAll(
(Clientes c) => {return c.Ciudad
c Ciudad == “A Coruña";}
);
}
}
Expresión
Lambda
Expresiones
p
Lambda
public class MiClase
{
public static void Main() {
List<Cliente> clientes = ObtenerListaClientes ();
List<Cliente> locales =
clientes.FindAll(c => c.Ciudad == “A Coruña");
}
}
Expresión
Lambda
Introduciendo LINQ
• Todos estos nuevos aspectos se trasladan a
métodos extensores sobre colecciones:
▫ Pueden transformarse en árboles de expresiones
ffrom p in passengers
i
where p.Citizenship== “ES"
select new { p Id p Name };
select new { p.Id, p.Name
passengers
.Where(p => c.Citizenship == “ES")
.Select(p => new { p.Id, p.Name });
Introduciendo LINQ
var pasajerosNacionales =
from p in passengers
where p.Citizenship == “ES"
I f
Inferencia
i
Tipos Variables select new {p.Id, p.Name};
Expresiones de
C
Consulta
l
Locales
Expresiones
Lambda
var pasajerosNacionales =
passengers
.Where(p => p.Citizenship== “ES")
.Select(p => new { p.Id, p.Name});
Select(p => new { p Id p Name});
Métodos
Extensores
Tipos
p
Anónimos
Inicializadores
de Objetos
Lenguaje Integrado de Consultas: LINQ
LINQ: Lenguage Integrated Query
• Lenguaje de consulta universal de primer orden en C# y
VB9
▫ Reducir el conocimiento de distintas formas de consulta.
▫ Parecido a lo que ya conocemos : SQL
▫ Basado en Lambda Cálculo, Tipado fuerte, Ejecución retrasada
(deferred) Utiliza características nuevas del lenguaje como:
Inferencia
e e c a de ttipos,
pos, Tipos
pos anónimos,
a ó
os, Métodos
étodos eextensores
te so es y
Inicialización de objetos
▫ Altamente extensible
• Múltiples
Múlti l proveedores
d
 Objects, XML, DataSets, SQL, Entities
 WMI, Sharepoint, Excel… incluso para Google, Flickr, Amazon
L
Language
INt
INtegrated
t d Query
Q
(LINQ)
VB
Others
Others…
C#
.NET Language-Integrated Query
LINQ enabled data sources
LINQ enabled ADO.NET
LINQ
To Objects
LINQ
T DataSets
To
D t S t
LINQ
T SQL
To
LINQ
T Entities
To
E titi
LINQ
To XML
<book>
<title/>
<author/>
<price/>
</book>
Objects
Relational
XML
Arquitectura de LINQ
var query = from p in passengers where p.Citizenship== “ES" select p
Fuente implementa
IEnumerable<T>
IEnumerable
<T>
Fuente implementa
IQueryable<T>
IQueryable
<T>
System.Linq.Enumerable
Basado en delegados
XML
Objetos
System.Linq.Queryable
Basado en árbol de expresión
SQL
DataSets
Entities
Expresión
ió de
d Consulta
C
l
Empieza
p
con
from
Cero o más from,
join, let, where, o
orderby
from id in source
{ from id in source |
join id in source on expr equals expr [ into
[ into id ] |
]|
let id = expr |
Termina con
where condition |
select o group by
orderby ordering, ordering, … }
select expr | group expr by key
[ into id query ]
Continuación
into opcional
Expresiones de Consulta
Proyección
Select <expr>
Filtrado
Where <expr>, Distinct
Comprobación
Any(<expr>) All(<expr>)
Any(<expr>),
Union
<expr> Join <expr> On <expr> Equals <expr>
Agrupación
Group By <expr>,
<expr> <expr> Into <expr>,
<expr> <expr>
Group Join <decl> On <expr> Equals <expr> Into
<expr>
Agregación
Count(<expr>), Sum(<expr>), Min(<expr>),
Max(<expr>), Avg(<expr>)
Partición
Skip [ While ] <expr>,
<expr> Take [ While ] <expr>
Conjunto
Union, Intersect, Except
Ordenación
Order By <expr>,
<expr> <expr> [ Ascending | Descending ]
Operadores de Consulta
Expresión de
consulta de Linq
Where(), Select()
Where()
Select(), SelecMany(),
SelecMany() OrderBy(),
OrderBy() ThenBy(),
ThenBy()
OrderByDescending(), ThenByDescending(), GroupBy(),
Join(), GroupJoin()
Partición
Take() Skip()
Take(),
Skip(), TakeWhile(),
TakeWhile() SkipWhile()
Conjunto
Distinct(), Union(), Intersect(), Except()
Conversión
ToArray(), ToList(), ToDictionary(), ToLookup(),
AsEnumerable(), Cast<T>(), OfType<T>()
Generación
Range(), Repeat<T>(), Empty<T>(), Concat(), Reverse()
Cuantificación
Any(), All(), Contains(), SequenceEqual()
Elementos
First(), Last(), Single(), ElementAt(), DefaultIfEmpty().
{
{método}OrDefault()
}
()
Agregados
Count(), LongCount(), Max(), Min(), Sum(), Average(),
Aggregate()
Lenguaje Integrado de Consultas: LINQ
LINQ To Objects
• Aplicable en colecciones genéricas y arrays que están en
memoria (heap)
• Métodos extensores para colecicones y arrays
▫ Using System.Linq;
• Las expresiones de consulta devuelven IEnumerable<T>
• Fundamental para gestionarlas de modo flexible
Ejemplos de consultas
Lenguaje Integrado de Consultas: LINQ
XML en .Net
Net Framework
• Clases XmlTextReader y XmlTextWriter
▫ L/E secuencial: Eficiente pero complejo
• Serialización y Deserialización:
System.Xml.Serialization
▫ Atributos en clases, S/D contra streams (ficheros, memoria…)
• Clases
l
XmlDocument,
l
XmlNode
l d … en System.Xmll
▫ Implementan un DOM por árboles
• Ahora: LINQ To XML
▫ Extensión de LINQ de .Net
▫ Simple,
Simple Flexible
Flexible, Potente
Potente, nuevo DOM
DOM.
▫ Manipulación y consulta con LINQ
LINQ To XML
• Importando System.Xml.Linq
• Nuevo DOM:
▫ Construcción funcional: XElement
• Independencia del documento
▫ Permite crear fragmentos XML sin asociarlos a un XDocument
• Texto como valor
▫ Hojas del árbol XML se convierten a tipos por valor de .Net
Clase XElement
• Los métodos están sobrecargados para localizar elementos
concretos.
• Métodos más representativos
.Load()
Load() / .Save()
Save()
Cargan o Guardan de un stream un documento XML
.Elements()
Secuencia de elementos contenidos
.ElementsBeforeSelf(),
(),
.ElementsAfterSelf()
Elementos “hermanos” anteriores o p
posteriores en el
mismo nivel del árbol
.Descendants{AndSelf}()
Secuencia aplanada de todos los elementos hijos
.Ancestors{AndSelf}()
Secuencia aplanada de todos los elementos padres
.Attributes()
Atributos del elemento
Creación de documentos
• Directamente con XElement
XElement contacts =
new XElement("Contacts",
new XElement("Contact",
new XElement("Name", "Patrick Hines"),
new XElement("Phone", "206-555-0144",
new XAttribute("Type", "Home")),
new XElement("phone", "425-555-0145",
new XAttribute("Type", "Work")),
new XElement("Address",
new XElement("Street1", "123 Main St"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042"))));
contacts.Save("contacts.xml");
Consultas
• Load(uri) (archivos
(archivos, http
http…))
• Métodos Elements, Attributes, Element, Attribute …
• Se puede utilizar Xpath (método XPathSelectElements())
XElement element = XElement.Load(Server.MapPath(@"~\XmlFiles\rssMiniNova.xml"));
…
XElement element = XElement.Load(@"http://www.mininova.org/rss.xml?cat=8");
var query = from i in element.Elements("channel").Elements("item")
element Elements("channel") Elements("item")
select new
{
Title = i.Element("title").Value,
Posted = DateTime.Parse(i.Element("pubDate").Value),
Size = Convert.ToDecimal(i.Element("enclosure").
Attribute("length").Value)
Link = i.Element("enclosure").Attribute("url").Value,
Category = i.Element("category").Value
};
Transformación de documentos
• Utilizando Linq y XElement
• Método Save(stream/fichero… ), ToString() …
<TSAInformationForm Date="...">
<SourceID>...</SourceID>
<PassengerList>
<Passenger DocumentId="...">
<Name>..</Name>
<Country> </Country>
<Country>..</Country>
<Flight Code="...">
<ArrivalDate>..</ArrivalDate>
</Flight>
</Passenger>
...
</PassengerList>
</TSAInformationForm>
XElement nuevo =
new XElement("TSAInformationForm",
new XAttribute("Date", DateTime.Now),
new XElement("SourceID", "883829HFGHMT"),
new XElement(
XElement("PassengerList",
PassengerList ,
from p in pasajeros
select new XElement("Passenger",
new XAttribute("DocumentId", p.Id),
new XElement("Name", p.Name),
new XElement("Country", p.Citizenship),
new XElement("Flight",
new XAttribute("Code",p.Code),
new XElement("ArrivalDate",p.Arrival)
))));
nuevo.Save("TsaSendFile.xml");
S
("T S dFil
l")
LINQ to Entities
• Arquitectura Entitiy Framework (EF)
• LINQ to Entities
• Ejemplos
Arquitectura de EF
• OR/M + Objetos de Servicio
▫
▫
▫
▫
▫
▫
Soporte de varios SGDB: EntityClientProvider
Herramientas y lenguaje para mapeado
Modelo Conceptual: EntityObject
Contextos tipados: ObjectContext
Gestión de Entidades: ObjectStateManager
Consulta: eSQL y LINQ To Entities
Patrón arquitectónico empresarial típico
Interface
Lógica de negocio
Almacén
public class Facade ADO.NET
ADO NET 3.0:
3 0: Entity Framework
{
Oracle
public static IList<Blog> GetAllBlogUpdatedSince(UpdatedSince period)
public
partial class BlogContext : ObjectContext {
{
Modelo Lógico
…
DateTime
dateBlog
= FacadeHelper.getPeriod(period);
public partial
class
:EntityObjects
EntityObject
EF
Clases
public
p
ObjectQuery<BlogPost>
j
y
g
BlogPosts
g
{
Data
UI /
{
using
ctx = new BlogContext())
public(BlogContext
static Blog CreateBlog(int
blogID,
Provider
get string seriesTitle, bool needsReviewer)
Fachada
{
UIC
SqlServer
SqlServer,
{
Stateless,
IQueryable<Blog>
blogs
=
from
blog
in
ctx.Blogs
{
Webforms,
Gestión
Modelo== null)) Oracle,
using
BlogsSample.BusinessLogic.ADONET30;
((this._BlogPosts
Short lived
Blogif
blog
= where
new Blog();
blog.BlogPosts.Any(p
Console
App,
MySQL,=> p.BlogDate > date)
ObjectContext,
…
{
contexts
blog.BlogID
g
g
=
blogID;
g
select blog;
g;
DB2, etc.
ASP
ASP.NET
ObjectStateManager
protected
t tNET
d void
id B
Button2_Click(object
tt 2 Cli k( bj tblog.SeriesTitle
sender,
d this._BlogPosts
E
EventArgs
tA = seriesTitle;
e)
) =
return
blogs.ToList<Blog>();
{ Web Services
base.CreateQuery<BlogPost>("[BlogPosts]");
blog.NeedsReviewer
= needsReviewer;
}
} blog;
GridView2.DataSource = Facade.GetAllBlogUpdatedSince(
CSDL return
}
<Schema
Namespace="BlogsSample.BusinessLogic.ADONET30.Model"
Alias="Self"
return this._BlogPosts;
}UpdatedSince.LastYear);
}
SGBD
xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
}
Metadata
GridView2.DataBind();
public
int BlogID
<EntityContainer
Name="BlogContext">
}
<E tit S t N
Name="BlogPosts"
"Bl P Archivos
t " E
EntityType="BlogsSample.BusinessLogic.ADONET30.Model.BlogPost"
tit
CSDL
CSDL,
T
MSL
"Bl y SSDL
S
l B i
L i ADONET30 M d l Bl P t" /
}
{ <EntitySet
…
…
get { return this._BlogID; }
public MSL
voidset
AddToBlogs(Blog blog)
<?xml version="1.0"
encoding="utf-8"?>
{
<Mapping
{ Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping
StorageEntityContainer="dbo"
CdmEntityContainer="BlogContext">
base.AddObject("Blogs",
blog);
this.OnBlogIDChanging(value);
Name="BlogPosts">
} <EntitySetMapping
Visual
del
Modelo
this
<E titthis.ReportPropertyChanging(
T Def.
M ReportPropertyChanging("BlogID");
i
T
N
"I T
Of(Bl
SBlogID
l B );
i
L i ADONET30 M d l Bl P t)">
<EntityTypeMapping
TypeName="IsTypeOf(BlogsSample.BusinessLogic.ADONET30.Model.BlogPost)">
<MappingFragment
StoreEntitySet="BlogPosts">
Archivo .EDMX
| Edmgen.exe
this._BlogID
=
StructuralObject.SetValidValue(value);
<ScalarProperty Name="BlogPostID" ColumnName="BlogPostID" />
this.ReportPropertyChanged("BlogID");
…
this.OnBlogIDChanged();
SSDL }
<?xml
version="1.0" encoding="utf-8"?>
}
}
<Schema
<S
h
N
Namespace="BlogsSample.BusinessLogic.BlogsModel.Store"
"Bl
S
l B i
L i Bl
M d l St
" Ali
Alias="Self"
"S lf"
ProviderManifestToken="09.00.3042" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="dbo">
...
<EntitySet Name="BlogComments"
EntityType="BlogsSample.BusinessLogic.BlogsModel.Store.BlogComments" />
Modelo Conceptual en EF
• Clases prescriptivas
▫
▫
▫
▫
▫
▫
Structural Object
j
> EntityObject
y j
Gestión de identidad (EntityKey)
Gestión de cambios (TrackingEntity
g
y event)
Soporte para relaciones (EntityCollection)
Estado (EntityState)
Son clases parciales
• Posibilidad de clases IPOCO
▫ Implementar IEntityWithKey,
IEntityWithChangeTracker, IEntityWithRelationship
Object Context
• Clase derivada (generada) de ObjectContext
• Tipado Fuerte: Manipulación del Modelo Conceptual
▫
▫
▫
▫
•
•
•
•
Consultas/Recuperación: Blogs: ObjectQuery;
Inserciones: .AddToBlog(Blog b); .AddObject(…),
Borrado: .DeleteObject
Persistencia: .SaveChanges();
Gestión de la conexión
Metadata (a partir de CSDL)
Almacen o caché en memoria de objetos
ac g de estado objetos:
Tracking
▫ .Attach(..), .Dettach(..)
▫ ObjectStateManager
▫ MergeOption
M
O ti
ObjectStateManager
• Seguimiento del estado de entidades
• Gest
Gestiona
o a eentradas
t adas EntityStateEntry
t tyState t y pa
para
a cada
Entidad en almacen en memoria.
▫
▫
▫
▫
▫
▫
Cuando se cargan (Query, Attach): Unchanged
Cuando se crean (AddObject): Added
Cuando se modifican: Changed
Cuando se borran: Deleted
Cuando se destruye el ObjectContext: Detached
Al aplicar ObjectContext.SaveChanges() en Added,
Changed, cambia a Unchanged.
Di ñ Entity
Diseño:
i Framework
k
EntityObject
Bl
Blog
*
1
EntityStateEntry
ObjectStateManager
CurrentValues
OriginalValues
State
IsRelationship
Caché de Entidades
Gestión de Identidad, estado y
cambios en las Entidades
Bl P t
BlogPost
BlogPostId: int
BlogEntry: string
…
EntityKey
EntityState:
Added, Deleted, Detached,,
Changed Unchanged
Changed,
PropertyChanged
1
ObjectContext
BloggerCtx
Blogs: ObjectQuery
BlogPosts: ObjectQuery
AddToBlogs(…)
AddT Bl P t ( )
AddToBlogPosts(…)
Hereda:
Attach(..)
Dettach(..)
Add(..)
( )
Delete(..),
Refresh(..)
SaveChanges(..) etc.
Consultas
• Entity SQL
ObjectQuery<Blog> query = ctx.CreateQuery<Blog>(
"SELECT VALUE bp.Blogs
p
g FROM BlogPosts
g
as bp
p WHERE bp.BlogDate
p
g
> @date",
new ObjectParameter("date",date));
▫ Dialecto SQL
Q indep.
p de g
gestor con soporte
p
p
para:
 Tipos enriquecidos, relaciones, herencia…
 Strings que se resuelven en tiempo de ejecución
• LINQ to Entities
ii
▫ Todas las ventajas de LINQ (tipado fuerte,
IQueryable<Blog> query = from posts in ctx.BlogPosts
expresiones
lambda)
where posts.BlogDate > date
▫ Lenguaje
que se
resuelve en tiempo de
select
posts.Blogs;
compilación
▫ Aprovechamos el tipado fuerte, la inferencia y el
Intellisense de Visual Studio
▫ Menos errores en ejecución
LINQ To Entities
• Diferencias con LINQ To Objects y To XML
• Las consultas tienen el tipo ObjectQuery<T>
▫ Implementa IQueryable<T> y no IEnumerable<T>
▫ Necesita Árboles de expresión para construir el SQL
final.
• Cuando se enumeran los resultados:
▫ query1.FirstOrDefault(), query1.ToList() …
▫ Se ejecuta la consulta SQL y devuelve un
IEnumerable<T>
• No están disponibles todos los operadores de Linq
To Objects
bj
o To XML
Arquitectura de LINQ To Entities
Operadores disponibles
Expresión de
consulta de Linq
Where(), Select(), SelecMany(), OrderBy(), ThenBy(),
OrderByDescending(), ThenByDescending(), GroupBy(),
Join(), GroupJoin()
Partición
Take(), Skip()
Conjunto
Distinct(), Union(), Intersect(), Except()
Conversión
ToArray(), ToList(), ToDictionary(), ToLookup(),
AsEnumerable(), Cast<T>(), OfType<T>()
Generación
N/A
Cuantificación
Any(), All()
Elementos
First(), Last(), ElementAt(). {método}OrDefault()
Agregados
Count(), LongCount(), Max(), Min(), Sum(), Average()
Cómo hacer una consulta
• Establecer el contexto
g ((FlightContext
g
ctx = new FlightContext())
g
()) { …}}
▫ Using
• Dentro del contexto construír la consulta
▫ Obtener los IQueryable<T> del Contexto
▫ IQueryable<Flight> query =
from f in ctx.Flights
where
h
p.To==“MAD”
T
“MAD”
select f;
• Ejecutar la consulta
▫ Con un operador de conversión
query ToList(); query.FirstOrDefault()
query FirstOrDefault() …
 query.ToList();
Otras consideraciones
• Pensar la consulta con el modelo conceptual
▫ Navegar por las relaciones y no con joins
• Los objetos
bj
recuperados
d dentro
d
d l contexto son
del
gestionados por el ObjectStateManager (tracking)
• Cuando se cierra el contexto NO.
NO
• Carga Perezosa de relaciones (dentro de un contexto)
▫ ¡¡No nos lo vamos a traer todo!!
▫ Si en el where se utiliza una relación, ésta se carga
▫ Carga implícita
 from f in ctx.Flights.Include(
ctx Flights Include(“Aircraft”)
Aircraft ) select f;
▫ Carga explícita
 if (!aflight.Aircraft.IsLoaded)
aflight.Aircraft.Load();
fli ht Ai
ft L d()
Modelo ER
Modelo EF
Lenguaje Integrado de Consultas: LINQ
Recursos
• MSDN: http//Msdn.microsoft.com
http//Msdn microsoft com
• 101 Linq Samples: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
• Blogs:
▫ ADO.NET Team Blog: http://blogs.msdn.com/adonet/
▫ Blog de Dany Simons: http://blogs.msdn.com/dsimmons/
▫ Blog de Unai Zorrilla: http://geeks.ms/blogs/unai/
http://geeks ms/blogs/unai/
▫ Blog de Octavio Hdez.: http://geeks.ms/blogs/ohernandez/
• Libros:
▫ “C# 3.0 y LINQ”, Octavio Hernández. Krasis Press 2007.
ISBN: 978-84-935489-1-9
▫ “ADO
ADO.NET
NET Entity Framework”
Framework , Unai Zorrilla,
Zorrilla Octavio
Hernández, Eduardo Quintás. Krasis Press 2008.
ISBN: 978-84-935489-9-5

Documentos relacionados