Solved

Repository pattern, ADO.Net Entity Framework: Update Method.

Posted on 2011-02-16
5
1,633 Views
Last Modified: 2012-05-11
HI!

I'm using the "Repository Pattern" and I like to have a Update method.

Need some help to write one.

This is what I have now.
public interface IRepository<T>
        where T : class
    {
        IEnumerable<T> FindAll();
        IEnumerable<T> FindBy(Expression<Func<T, bool>> filter);

        T FindById(int id);
        T FindById(string id);

        bool Add(T entity);
        bool Update(T entity);
        bool Remove(T entity);
    }


public class FileSystemWatcherRepository : IRepository<FileSystemWatcher>
{
    public IEnumerable<FileSystemWatcher> FindAll()
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Return all
            return ctx.FileSystemWatcher.ToArray();
        }
    }

    public IEnumerable<FileSystemWatcher> FindBy(Expression<Func<FileSystemWatcher, bool>> filter)
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Return item according to predicate 
            return ctx.FileSystemWatcher.Where(filter);
        }
    }

    public FileSystemWatcher FindById(int id)
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Return item by Id
            return ctx.FileSystemWatcher.Where(d => d.FileSystemWatcherId == id).FirstOrDefault();
        }
    }

    public FileSystemWatcher FindById(string id)
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Return item by folder path id
            return ctx.FileSystemWatcher.Where(d => d.FolderPath == id).FirstOrDefault();
        }
    }

    public bool Add(FileSystemWatcher entity)
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Add object to entity
            ctx.FileSystemWatcher.AddObject(entity);

            // Commit
            ctx.SaveChanges();

            // All ok
            return true;
        }
    }

    public bool Update(FileSystemWatcher entity)
    {
        ???
    }

    public bool Remove(FileSystemWatcher entity)
    {
        using (var ctx = new FbiDmsEntities())
        {
            // Delete object from entity
            ctx.FileSystemWatcher.DeleteObject(entity);

            // Commit
            ctx.SaveChanges();

            // All ok
            return true;
        }
    }
}

Open in new window

0
Comment
Question by:ulf-jzl
  • 3
  • 2
5 Comments
 
LVL 21

Accepted Solution

by:
Craig Wagner earned 500 total points
ID: 34912604
Simplest way would be to retrieve the existing object, copy the values from the incoming object, and save changes.

        using (var ctx = new FbiDmsEntities())
        {
            FileSystemWatcher fsw = ctx.FileSystemWatcher.Where(d => d.FolderPath == id).SingleOrDefault();

            // Copy values from entity to fsw
            // fsw.Property1 = entity.Property1;
            // fsw.Property2 = entity.Property2;

            // Commit
            ctx.SaveChanges();
        }

You may want to combine Add and Update into a single method because if the query to find an existing FileSystemWatcher returns nothing you may want to just go ahead and add a new one.

One thing I noticed was that Methods that Remove and Add both return a bool, but the only thing they ever return is true. In my opinion those methods shouldn't return anything, they will either work or they will throw an exception.

At my place of work we implemented a modified Repository/UnitOfWork pattern. The Repository maintains a reference to the object context that is used for the life of the repository. In order to do an update the calling code simply retrieves the object(s) it wants to update (they'll still be attached to the context because we never dispose the context until the repository is disposed), changes the property value(s), then calls Commit() on the repository/unit of work.
0
 

Author Comment

by:ulf-jzl
ID: 34913931
thx man. :)

One question more, if you have the time. :)

I have a Store Procedure that executes the INSERT statement, I have done all the mapping and it works fine. The first insert works, but when I run it again it shold return affected rows  = zero.
But it always returns 1, even if the store procedure is empty.

If you have any thoughts about the code, please tell me, maybe I have done something strange. :)
[TestMethod]
public void AddTest()
{
    // Arrange
    IRepository<FileSystemWatcher> repository = new FileSystemWatcherRepository();

    FileSystemWatcher entity = new FileSystemWatcher() { FolderPath = @"C:\Test" };

    // Act
    bool actual = repository.Add(entity);

    // Assert
    Assert.IsTrue(actual);
}

public bool Add(FileSystemWatcher entity)
{
    // Get Entity
    using (var ctx = new FbiDmsEntities())
    {
        // Add object to entity
        ctx.AddToFileSystemWatcher(entity);

        // Commit
        int result = ctx.SaveChanges();

        // Affected rows
        if (result == 1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

Use [FBI.DMS]; 
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
SET NOCOUNT ON;
GO	
-- ====================================================
-- Author:		
-- Create date: 2011-02-13
-- Description:	Insert a folder path
-- ====================================================
IF OBJECT_ID('InsertFileSystemWatcher') IS NOT NULL
	DROP PROC InsertFileSystemWatcher;
GO

CREATE PROCEDURE InsertFileSystemWatcher
(
	@FolderPath varchar(300)
)
AS
DECLARE @Id int;

BEGIN TRANSACTION FileSystemWatcherInsert
    WITH MARK N'Inserting a file system watcher folder path';
    
BEGIN
	-- Stops the message that shows the count of the number of rows affected
	SET NOCOUNT ON;
		
	-- Check so this folder path already exists
	SELECT @Id = [FileSystemWatcherId]
		 
	FROM dbo.[FileSystemWatcher]
	
	WHERE 
		[FolderPath] = 'C:\Test';		
END;

BEGIN
	--State 1: Do not insert if the folder path already exists, raise error
	IF 	@Id IS NULL
		BEGIN
			-- INSERT folder path	 	
			INSERT 
		         
			INTO dbo.[FileSystemWatcher]
			(
				[FolderPath]
			)
			VALUES
			(
				@FolderPath
			);			
		END;
	ELSE
		BEGIN
			RAISERROR ('The record already exists in the database.', 1, 1); 
		END;		
END;
	
-- commit the transaction
COMMIT TRANSACTION FileSystemWatcherInsert;
GO


-------------------------------------
Table
-------------------------------------
USE [FBI.DMS]
GO

/****** Object:  Table [dbo].[FileSystemWatcher]    Script Date: 02/17/2011 08:48:35 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[FileSystemWatcher](
	[FileSystemWatcherId] [int] IDENTITY(1,1) NOT NULL,
	[TimeStamp] [datetime] NOT NULL,
	[FolderPath] [nchar](300) NOT NULL,
 CONSTRAINT [PK_FileSystemWatcherSettings] PRIMARY KEY CLUSTERED 
(
	[FileSystemWatcherId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[FileSystemWatcher] ADD  CONSTRAINT [DF_FileSystemWatcherSettings_TimeStamp]  DEFAULT (getdate()) FOR [TimeStamp]
GO

Open in new window

0
 
LVL 21

Expert Comment

by:Craig Wagner
ID: 34916579
This really should be a separate question with its own points assigned, but...

I'm not sure that I understand the comment that "the store procedure is empty." Stored procedures can't be empty, unless you mean the body of the stored procedure (i.e. it's an empty stored procedure that does nothing).

However, looking at the stored proc your problem would appear to be this line:

      WHERE
            [FolderPath] = 'C:\Test';

You're hard-coding the folderpath instead of comparing it to the one that's being passed in. So unless the first one you pass in is 'C:\Test' it will keep adding new ones. It should be:

      WHERE
            [FolderPath] = @FolderPath
0
 

Author Comment

by:ulf-jzl
ID: 34916799
I will move this to another question, so you can help me there instead.
Thx for the error, but what I mean is.

The ctx.SaveChanges();  always returns 1. even if I would empty the body of the store procedure.

The error I had did not solve the problem. it still return one even if it did not add any data to the table.

0
 

Author Comment

by:ulf-jzl
ID: 34916961
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Let's review the features of new SQL Server 2012 (Denali CTP3). It listed as below: PERCENT_RANK(): PERCENT_RANK() function will returns the percentage value of rank of the values among its group. PERCENT_RANK() function value always in be…
JSON is being used more and more, besides XML, and you surely wanted to parse the data out into SQL instead of doing it in some Javascript. The below function in SQL Server can do the job for you, returning a quick table with the parsed data.
Via a live example, show how to extract insert data into a SQL Server database table using the Import/Export option and Bulk Insert.
This videos aims to give the viewer a basic demonstration of how a user can query current session information by using the SYS_CONTEXT function

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now