---
title: "Entity framework och repositories."
type: "forum-thread"
url: "https://www.webforum.nu/amne/dotnet/177038-entity-framework-och-repositories"
topic: ".NET"
topic_url: "https://www.webforum.nu/amne/dotnet"
author: "Fredde Mannen"
published: "2009-02-20T08:28:26.000Z"
updated: "2009-02-27T18:38:47.000Z"
replies: 15
views: 897
page: 1
pages: 1
language: "sv-SE"
site: "webForum — webforum.nu"
rights: "Upphovsrätten till varje inlägg tillhör dess författare."
attribution: "Citera som: webForum, https://www.webforum.nu/amne/dotnet/177038-entity-framework-och-repositories"
---

# Entity framework och repositories.

## #1 — Fredde Mannen, 2009-02-20T08:28Z

Sitter och labbar lite med entity framework, och dyker på lite funderingar. Inga speciella stora svårigheter ännu, håller mig till rätt simpla saker.

Byggt ett baseobject för repositories med lite grundläggande funktionalitet: 

```
Imports System.Linq.Expressions
Imports System.Data.Objects
Imports System.Configuration

Public MustInherit Class RepositoryBase(Of TEntity)
#Region "Mustoverride methods"
	Public MustOverride Sub MarkAsDeleted(ByVal entity As TEntity)
#End Region

#Region "Generall methods"
	Public Function GetAll() As IEnumerable(Of TEntity)
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction
		Dim entities As IEnumerable(Of TEntity) = Nothing

		Try
			entities = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name))
			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception
			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entities
	End Function

	Public Function GetByKey(ByVal where As Func(Of TEntity, Boolean)) As TEntity
		Dim entity As TEntity = Nothing
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction

		Try
			If Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where).Count > 1 Then
				Throw New Exception("Not unique entity.")
			Else
				entity = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where).First
			End If

			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception

			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entity
	End Function

	Public Function GetByFilter(ByVal where As Func(Of TEntity, Boolean)) As IEnumerable(Of TEntity)
		Dim entities As IEnumerable(Of TEntity) = Nothing
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction

		Try
			entities = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where)

			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception
			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entities
	End Function
#End Region

#Region "Datacontext"
	Friend Function Context() As Domain.DataModelContainer
		Dim entityConnectionString As String = ConfigurationManager.ConnectionStrings("DataModelContainer").ConnectionString

		Dim connection As New EntityClient.EntityConnection(entityConnectionString)
		connection.Open()
		Return New Domain.DataModelContainer(connection)
	End Function
#End Region
End Class
```

Funkar bra än så länge i alla fall.. på test och labb nivå. :)

När man lägger till entiteter från databasen ex. Customers, Employees, Suppliers.

Så skapar designern exakt samma objekt.. Customers, Employees Suppliers.. 

Känns lite dumt bara, skulle vara bättre om det var som i Linq To Sql, att de då blir customer, employee och supplier. 

Alternativ är ju att byta namn på dem i modellen eller i databasen, byter jag namn på dem i modellen så funkar givetvis inte min ovanstående kod. 

Låter så dumt tycker jag: 

```
Dim employee As New Employees

With employee
 .FirstName = "Kalle"
 .LastName = "Andersson
End employee
```

ge mig lite tankar och lite vägledning kanske, och ge gärna någon kommentar på koden i baseobjektet också. :)

Permalänk: https://www.webforum.nu/p/177038

## #2 — Zaiman, 2009-02-20T08:41Z

Den här tråden kanske kan ge dig lite tips :)
<http://www.webforum.nu/showthread.php?t=163666&highlight=entity>

Permalänk: https://www.webforum.nu/p/2169671

## #3 — Fredde Mannen, 2009-02-20T09:20Z

> **[Zaiman skrev:](https://www.webforum.nu/p/1457314)**
>
> Den här tråden kanske kan ge dig lite tips :)
> <http://www.webforum.nu/showthread.php?t=163666&highlight=entity>

 Mja.. Det är ju Glads Entitymapper. 

Min entitetsmappning sker ju via Entity Framework från Microsoft. 

Kanske missar poängen! :)

Permalänk: https://www.webforum.nu/p/2169672

## #4 — erka, 2009-02-20T11:42Z

OT: En vanlig förkommande grej med Repon är att det är mycket metoder i dem, mestadels för Find-saker, ett tips eftersom du kan linq:a är att helt bryta ut efter ett Finder-pattern eller implementera specification pattern.

Permalänk: https://www.webforum.nu/p/2169690

## #5 — Fredde Mannen, 2009-02-20T12:16Z

> **[erka skrev:](https://www.webforum.nu/p/1457336)**
>
> OT: En vanlig förkommande grej med Repon är att det är mycket metoder i dem, mestadels för Find-saker, ett tips eftersom du kan linq:a är att helt bryta ut efter ett Finder-pattern eller implementera specification pattern.

Funderade lite på det där med ett Specification-pattern.. har dock inte läst om det än. 

Dock funderade jag på att ha mitt grundläggande finder metod i base: 

```
Public Function GetByFilter(ByVal where As Func(Of TEntity, Boolean)) As IEnumerable(Of TEntity)
		Dim entities As IEnumerable(Of TEntity) = Nothing
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction

		Try
			entities = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where)

			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception
			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entities
	End Function
```

För att sedan i ex. EmployeeRepository 

```
Public Function GetByFirstname(firstName As String) As IEnumrable(Of Domain.Employees)
  Return MyBase.GetByFilter(Function(e) e.FirstName.StartsWith(firstName))
End Function
```

Kan ju alltid labba lite med Specification-pattern också! :)

Permalänk: https://www.webforum.nu/p/2169693

## #6 — erka, 2009-02-20T13:32Z

Egentligen kan du dra ut så dina finders enbart jobbar med linqfrågor, och på sättet isolera dem för testning effektivare. Det kräver dock att om du vill att repon ska dela på Findermetoder såsom ById etc. att du implementerar ett interface på de klasser som kan identifiera dem på Id utan reflection. Specification pattern är inte alltid rätt om du bara ska kunna hitta saker, utan kommer i sin rätt när du vill kombinera olika förutsättningar för att hitta något, eller då du har villkor som du inte har definierade i din domän via properties. Fowler har skrivit en bra PDF om specification pattern. 

<http://martinfowler.com/apsupp/spec.pdf>

Du hittar en variant av finder som du kanske kan sno idér från på <http://russelleast.wordpress.com/2008/09/20/implementing-the-repository-and-finder-patterns/>, för nhibernate men principen är den samma :)

Permalänk: https://www.webforum.nu/p/2169707

## #7 — Fredde Mannen, 2009-02-20T14:14Z

Laborerade vidare..

Laborerade lite vidare på detta med specifications.

Kom fram till detta: 

```
Imports System.Linq.Expressions
Public Interface ISpecification(Of TEntity)
	ReadOnly Property Predicate() As Expression(Of Func(Of TEntity, Boolean))
	Function IsSatisfiedBy(ByVal entity As TEntity) As Boolean
End Interface
```

```
Imports System.Linq.Expressions
Public Class Specification(Of T)
	Implements ISpecification(Of T)

	Private ReadOnly _predicate As Expression(Of Func(Of T, Boolean))
	Public Sub New(ByVal predicate As Expression(Of Func(Of T, Boolean)))
		_predicate = predicate
	End Sub
	Public ReadOnly Property Predicate() As Expression(Of Func(Of T, Boolean)) Implements ISpecification(Of T).Predicate
		Get
			Return _predicate
		End Get
	End Property
	Public Function IsSatisfiedBy(ByVal entity As T) As Boolean Implements ISpecification(Of T).IsSatisfiedBy
		Return _predicate.Compile().Invoke(entity)
	End Function

	' Implementera en Or och en And tror jag.. 
End Class
```

Kastade in i mitt BaseRepository

```
	Protected Function GetBySpecification(ByVal where As ISpecification(Of TEntity)) As IEnumerable(Of TEntity)
		Dim entities As IEnumerable(Of TEntity) = Nothing
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction

		Try
			entities = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where.Predicate.Compile)

			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception
			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entities
	End Function
```

Exempel på en EmployeeSpecification. 

```
Imports System.Linq.Expressions

Public Class EmployeeSpecification
	Public Shared ReadOnly Property DeletedEmployees() As Specification(Of Domain.Employees)
		Get
			Dim specification As Expression(Of Func(Of Domain.Employees, Boolean)) = Function(e) e.IsDeleted.Equals(True)
			Return New Specification(Of Domain.Employees)(specification)
		End Get
	End Property
End Class
```

Tror dock att jag skall ta och läsa lite på Fowler samt NHibernate implementeringen. Samt läsa på lite mer om de olika patterns som finns. :)

Men tycker det är nice övning för att lära sig Vb.Net bättre. :)

Permalänk: https://www.webforum.nu/p/2169709

## #8 — erka, 2009-02-20T15:32Z

Läs och begrunda Fowler-artikeln, jag feltolkade också specificationpattern innan en vän tipsade mig om den artikeln och la ut hur jag hade feltolkat det :) Eller snarare, jag blev lite överkåt på det hehe, inte så många scenarion som gör spec.pattern nödvändigt, ofta bättre med finder, olika ändamål, men men :)

Permalänk: https://www.webforum.nu/p/2169717

## #9 — Gladh, 2009-02-23T16:04Z

En sak som jag gillar med Linq är deras IQueryable interface. Nu har jag inte implementerat det, men om jag byggde Repositorys på Linq/EF så skulle jag försöka få till en metod som kan ta emot ett "Linq statement" och exekvera det inne i repositoryn så att du får tillbaka en IEnumerable från metoden. Det hade varit smutt.... 

\- M

Permalänk: https://www.webforum.nu/p/2169995

## #10 — erka, 2009-02-23T17:48Z

I min värld går det lite emot tanken med Repositories, inom DDD ligger ansvaret att definera hur man kan kommunicera med sin domän, vad man kan få ut. Inte lägga ansvaret för hur och vad, på den som nyttjar repot. Vilket ditt förslag skulle innebära Gladh. Men så länge man inte exponerar en IQueryable\<T\> så kanske det inte bidrar med några drastiskt dåliga resultat :)

Freddemannen, kom att tänka på en sak som kan vara vettig för att förtydliga vart du kanske behöver specifications eller någon form av query-objekt. Låt oss säga att du har en property som räknas ut på ditt objekt, och du vill ställa en fråga som baseras på att denna property har ett visst värde. EF och Linq 2 SQL kommer då läsa upp alla dina objekt ur DB och sedan gör operationer på dessa för att hitta vilka som matchar. Det vill man undvika :)

Permalänk: https://www.webforum.nu/p/2170003

## #11 — Fredde Mannen, 2009-02-24T09:19Z

> **[erka skrev:](https://www.webforum.nu/p/1457694)**
>
> I min värld går det lite emot tanken med Repositories, inom DDD ligger ansvaret att definera hur man kan kommunicera med sin domän, vad man kan få ut. Inte lägga ansvaret för hur och vad, på den som nyttjar repot. Vilket ditt förslag skulle innebära Gladh. Men så länge man inte exponerar en IQueryable\<T\> så kanske det inte bidrar med några drastiskt dåliga resultat :)
> 
> Freddemannen, kom att tänka på en sak som kan vara vettig för att förtydliga vart du kanske behöver specifications eller någon form av query-objekt. Låt oss säga att du har en property som räknas ut på ditt objekt, och du vill ställa en fråga som baseras på att denna property har ett visst värde. EF och Linq 2 SQL kommer då läsa upp alla dina objekt ur DB och sedan gör operationer på dessa för att hitta vilka som matchar. Det vill man undvika :)

Btw. Läste lite från Fowler där han nämnde att det inte fanns några bra referenser till applikationer som nyttjats sig av Specifikation-pattern. 

Dock däremot där jag tänker mig att man kan nyttja sig av en specifikation är kanske att jag ex en kunddatabas där vi har Guldkunder, Silverkund, Bronskunder osv. och deras status beror på hurlänge de varit kunder, eller antalet produkter de handlat genom tiden.  Alternativen skulle kunna vara  

```
customerRepository.GetByGoldStatus()
customerRepository.GetBySilverStatus()
customerRepository.GetByBronzeStatus()
```

eller kanske rent av implementera ett specifikation på dessa som man nyttjar på följande sätt.

```
customerRepository.GetAll(CustomerStatusSpecifikation.GoldCustomers)
customerRepository.GetAll(CustomerStatusSpecifikation.SilverCustomers)
customerRepository.GetAll(CustomerStatusSpecifikation.BronzeCustomers)
```

Hur ser ni på den tanken?

Permalänk: https://www.webforum.nu/p/2173176

## #12 — Gladh, 2009-02-24T15:44Z

> **erka skrev:**
>
> I min värld går det lite emot tanken med Repositories, inom DDD ligger ansvaret att definera hur man kan kommunicera med sin domän, vad man kan få ut. Inte lägga ansvaret för hur och vad, på den som nyttjar repot. Vilket ditt förslag skulle innebära Gladh

Tja ansvaret för vad som kommer att komma ur ditt repository kommer alltid att vila på den som anropar det, hur du än vrider och vänder på det. Och hur kan jag påstå detta då?

Enkelt! Du har följande repository.

```
public Customer GetCustomerById(int id){...}
public Customer GetCustomerByName(string name){...}
public Customer GetCustomerByCompany(Company company){...}
```

Det som kommer ut från detta repository beror ju på vad du stoppar in i parameterna. Så om du anropar GetCusomerById(3) så är det ju den anropande funktionen som sätter värdet 3 ;)

Och det var lite det som jag var uteefter även om jag inte beskrev det så klart, att det är inte hela LINQ satsen som jag skulle vilja skicka in, utan egentligen bara WHERE delen vilket ju så fall hade gett mig en metod att anropa istället för de 3 i ovanstående exempel.  

Det hade blivit lite som Specifikation pattern, bara att min metod i repositoryn hade blivit fan så mycket mindre och enklare utan 58 miljoner vilkorsatser för att bygga ihop rätt statement i slutändan.

Så egentligen är det inte IQueryable interfacet som jag är ut efter. Jag vet vad du menar och har haft den diskutionen förut, och de motreaktioner man får på att använd sig av en IQueryable inne i sin kod är att du kanske inte får den data som du förväntar dig eftersom själva frågan körs inte i repositoryn utan "senare" i koden. 

\- M

Permalänk: https://www.webforum.nu/p/2173231

## #13 — Fredde Mannen, 2009-02-24T16:21Z

> **[Gladh skrev:](https://www.webforum.nu/p/1457849)**
>
> Det som kommer ut från detta repository beror ju på vad du stoppar in i parameterna. Så om du anropar GetCusomerById(3) så är det ju den anropande funktionen som sätter värdet 3 ;)
> 
> Och det var lite det som jag var uteefter även om jag inte beskrev det så klart, att det är inte hela LINQ satsen som jag skulle vilja skicka in, utan egentligen bara WHERE delen vilket ju så fall hade gett mig en metod att anropa istället för de 3 i ovanstående exempel.  
> 
> Det hade blivit lite som Specifikation pattern, bara att min metod i repositoryn hade blivit fan så mycket mindre och enklare utan 58 miljoner vilkorsatser för att bygga ihop rätt statement i slutändan.
> 
> Så egentligen är det inte IQueryable interfacet som jag är ut efter. Jag vet vad du menar och har haft den diskutionen förut, och de motreaktioner man får på att använd sig av en IQueryable inne i sin kod är att du kanske inte får den data som du förväntar dig eftersom själva frågan körs inte i repositoryn utan "senare" i koden. 
> 
> \- M

Är inte lite som att skicka in en filtermetod liknande denna 

```

Public Function GetByFilter(ByVal where As Func(Of TEntity, Boolean)) As IEnumerable(Of TEntity)
		Dim entities As IEnumerable(Of TEntity) = Nothing
		Dim transaction As IDbTransaction = Context.Connection.BeginTransaction

		Try
			entities = Context.CreateQuery(Of TEntity)(String.Format("[{0}]", GetType(TEntity).Name)).Where(where)

			transaction.Commit()

			Context.Connection.Close()
		Catch ex As Exception
			transaction.Rollback()
			Context.Connection.Close()
		End Try

		Return entities
	End Function
```

Där where satsen är en Lamda-sats.  

```
Function(c) c.CustomerName.StartsWith("A")
```

Eller?
Dock kanske inte ultimat.. men åt det hållet?

Permalänk: https://www.webforum.nu/p/2173236

## #14 — Gladh, 2009-02-26T13:41Z

Jo typ något sådant hade varit underbart, hur det fungerar rent prestanda mässigt har jag ingen anning och dessutom så suger jag på VB.NET men det är något sådant som jag tänkt mig. 

CreateQuery metoden är det någon egendefinerad eller till hör den någon OR-Mapper?

\- M

Permalänk: https://www.webforum.nu/p/2173520

## #15 — Fredde Mannen, 2009-02-27T10:17Z

> **[Gladh skrev:](https://www.webforum.nu/p/1458173)**
>
> Jo typ något sådant hade varit underbart, hur det fungerar rent prestanda mässigt har jag ingen anning och dessutom så suger jag på VB.NET men det är något sådant som jag tänkt mig. 
> 
> CreateQuery metoden är det någon egendefinerad eller till hör den någon OR-Mapper?
> 
> \- M

Den tillhör en ORM-mapper.

Permalänk: https://www.webforum.nu/p/2173604

## #16 — CatZ, 2009-02-27T18:38Z

Jag har en specification pattern jag sitter och pillar på ibland. Jag har NÄSTAN lyckats få till And & Or i Entity Framework men det vill sig inte riktigt än. Kanske skulle posta den ofärdig här så kan vi hjälpas åt att sätta ihop den?

Edit: Glömde säga att det är generiskt. Visst det håller inte i alla lägen men till enklare data access gör jag bara

```
ICriterion<User> criterion = new Criterion<User>(u => u.ID == 1);
var repository = new Repository();
var user = repository.GetBy(criterion);
```

Det jag saknar är att kunna lägga till & eller \| och producera ett resultat på flera kriterium. Men det ska jag nog få till tids nog. Jäkligt smidig lösning i mindre projekt är det i alla fall :)

Permalänk: https://www.webforum.nu/p/2173637

---

Tråden på webben: https://www.webforum.nu/amne/dotnet/177038-entity-framework-och-repositories
