Code Monkey home page Code Monkey logo

dbcontextscope's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dbcontextscope's Issues

Problems when attaching new dbcontexts while performing savechanges

Backstory: I have implemented repositories that store the data. In each of the DbContext models i have attached an auditlog handler to catch changes and log them using another repository.

    public override int SaveChanges(bool acceptAllChangesOnSuccess)
    {
        AuditLog[] logs = null;

        if (_auditLogTracker != null)
            logs = _auditLogTracker.TrackChanges(this);

        var result = base.SaveChanges(acceptAllChangesOnSuccess);

        if (_auditLogTracker != null && logs != null)
            _auditLogTracker.Save(logs);

        return result;
    }

Error: Collection was modified; enumeration operation may not execute.

The error is due to a new context being added while looping through contexts and performing commit.
Could the DbContextCollection perform other than foreach loops to go through the list to allow for new contexts being added during savechanges?

for(var i = 0; i contexts.length; i++)
{
//would probably allow for dynamicly injected contexts
}

asp.net thread agility

Might we have problems using callcontext in asp.net / wcf applications ? Wouldn't it be better if you use HttpContext.Current.Items / OperationContext.Current.Extensions for asp.net / wcf ?

Connect to database with a different user/connection string

I am currently using this, I think, by the book and it's awesome. But I came across a problem I'm unsure how to solve today. I have a query that I need to execute using a different database login/user because it requires additional permissions. I can create another connection string in my web.config, but I'm not sure how to specify that for this query, I want to use this new connection string. Here is my usage:

In my logic layer:
private static IDbContextScopeFactory _dbContextFactory = new DbContextScopeFactory();

public static Guid GetFacilityID(string altID)
{
            ...
            using (_dbContextFactory.CreateReadOnly())
            {
                entity = entities.GetFacilityID(altID)
            }
}

That calls into my data layer which would look something like this:

private AmbientDbContextLocator _dbcLocator = new AmbientDbContextLocator();

    protected CRMEntities DBContext
    {
        get
        {
            var dbContext = _dbcLocator.Get<CRMEntities>();

            if (dbContext == null)
                throw new InvalidOperationException("No ambient DbContext....");

            return dbContext;
        }
    }

    public virtual Guid GetFaciltyID(string altID)
    {
        return DBContext.Set<Facility>().Where(f => f.altID = altID).Select(f => f.ID).FirstOrDefault();
    }

Currently my connection string is set in the default way:

public partial class CRMEntities : DbContext
{
    public CRMEntities()
        : base("name=CRMEntities")
    {}
}

Is it possible for this query to use a different connection string?

Please help : Inserted item ID not populated

Hi,

Recently I found your DbContextScope, and I find project very interesting.
I wanted to test it but I encounter some issue.

Explanation :

BUSINESS LAYER:
"ClientManager"

        public int Insert(Client client)
        {
            using (var context = _dbContextScopeFactory.Create())
            {
                CLIENT object = ClientMapper.Instance.Map(client);
                object = _clientRepository.Add(object);
                context.SaveChanges();
                client.IdClient = objet.ID_CLIENT;
                return object.ID_CLIENT;
            }
        }

"AddressManager"

     public int Insert(Address address)
        {
            using (var context = _dbContextScopeFactory.Create())
            {
                ADDRESS object = AddressMapper.Instance.Map(address);
                _addressRepository.Add(object);

                context.SaveChanges();

                return object.ID_ADRESSE;
            }
        }

I have my console program for test and it's works fine.

But now if I want to add to "ClientManager" another function:

     public int InsertClientWithAddress(Client client, Adresse address)
        {
            using (var context = _dbContextScopeFactory.Create())
            {
                int id = Insert(client)
                address.IdClient = id; // = 0 because no SaveChanges
                _addressManager.Insert(address);

                context.SaveChanges();

                return client.IdClient;
            }
        }

It's not working because my client ID is auto-increment integer in database and it's not initialized because of DbContextScope.SaveChanges

How I can resolve this issue with your framework?

Thanks you in advance

P.S

Sorry for my English :)

How do I use this with transaction?

I am trying to figure out what is the correct way to start a transaction and prepare for rollback in case of error...

I notice there is DbContextScopeFactory.CreateWithTransaction(IsolationLevel) in the code but couldn't figure it out how to actually use it.

Is this the proper way to do it?

using (var dbContextScope = DbContextScopeFactory.CreateWithTransaction(IsolationLevel.ReadCommitted))
{
  var dbContext = dbContextScope.DbContexts.Get<MyDbContext>();
  using (var trans = dbContext.Database.BeginTransaction())
  {
      try
      {
          ... do some work here.. modify several tables etc..

         dbContext.SaveChanges();
         trans.Commit();
      }
      catch (Exception)
      {
         trans.Rollback();  //rolback everything
         throw;
      }
  }
}

TDD with DbContextScope

Hi,

I am wondering how can I implement TDD with DbContextScope. I have seen some of the methods such as Repository pattern and using Effort package. I am a beginner in TDD, so I am struggling with dependencies break down. I looked into couple of SO discussions but using moq framework seems to be an overkill ? ( as unit tests should be simple)

Thanks in advance !

Conflict with Ninject interception?

Hello,

I have been using DbContextScope for a while in my project but started to have an issue recently. I have added Ninject interceptor in order to do dome basic logging in my Service layer classes. Here is an example of module configuration:

Bind<IClientFileService>().To<ClientFileService>().InRequestScope().Intercept().With<LogErrorInterceptor>();

Once that change got introduced I started to receive "Non-static method requires a target" exception on DbContextScope.SaveChangesAsync invocation (the stack trace is attached).

What could I do to be able to use these two functions together?

Thanks,
Anton

StackTrace.txt

SaveChanges called only once, question

Why this?

// Only save changes if we're not a nested scope. Otherwise, let the top-level scope 
// decide when the changes should be saved.
var c = 0;
if (!_nested)
{
    c = CommitInternal();
}

I find this problematic in the scenario I need an auto generated id from one insert to be logged for example.
I did overcome the problem by calling the specific context's SaveChanges method, is there any problem?

I like how all this works, however will like to understand better what are the pros and cons of preventing partial SaveChanges.

Thanks

DbContext disposed if Service function called twice

I have a generic repository pattern implemented where I set my dbcontext from ambientDbContextLocator. In my service I have using block for dbcontextScopeFactory where repository is used for query.

using (var dbContextScope = _dbContextScopeFactory.Create())
{
_peopleRepository.Table.Where(x => x.Id == id);
}

calling this service function once is fine, but second call says DbContext has been disposed. Tried usign CreateReadOnly as well but no luck. Am I doing something wrong here?

Same schema for many databases

We have many databases all exactly the same. We may open more than one context that are the same type. We use a generated connection string to accomplish this. Will this system know the difference between contexts when the type is the same but the connection is different ?
Thanks

Suggestion on how to deal with scopes in Application layer that does not depend on Infrastructure layer

In my setup I have the Domain layer, the Application Layer on top of it, and then a layer with Infrastructure, and Presentation on top of that. Generally known as the Onion architecture.

I process my use cases in the form of Commands or Queries in the Application Layer, receiving them from the Presentation Layer.
In the C/Q handlers i'm pulling in infrastructure services to materialize my entities.
The domain layer is then called to execute the use cases, perhaps with the assistance of domain services and perhaps other types of infrastructure services.
Possibly queueing up events to be processed before or after initiating the DB transaction (e.g sending notifications by either email or SignalR, or kicking up background work through ServiceBus queues).

I do not use repositories, and thus I grab DbContexts based on interfaces into my application layer. The problem being that DbContextScope relies on DbContext implementations instead, which I do not have access to.

I came up with the following workaround for my problem:

    public static class DbContextScopeExtensions
    {
        // These are set from the composition root
        public static Func<IAmbientDbContextLocator, ISqlContext> GetSqlContextFromLocator;  // locator.Get<W6Context>();
        public static Func<IDbContextCollection, ISqlContext> GetSqlContextFromCollection; // collection.Get<W6Context>();

        public static ISqlContext GetSqlContext(this IAmbientDbContextLocator locator) {
            return GetSqlContextFromLocator(locator);
        }

        public static ISqlContext GetSqlContext(this IDbContextCollection collection) {
            return GetSqlContextFromCollection(collection);
        }
    }

as alternative, in Generic form:

    public static class DbContextScopeExtensions
    {
        // These are set from the composition root
        // if (type == typeof (ISqlContext)) return locator.Get<W6Context>();
        public static Func<IAmbientDbContextLocator, Type, IDbContext> GetDbContextFromLocator;

        // if (type == typeof (ISqlContext)) return collection.Get<W6Context>();
        public static Func<IDbContextCollection, Type, IDbContext> GetDbContextFromCollection;

        public static T GetByInterface<T>(this IAmbientDbContextLocator locator) where T : class, IDbContext {
            return GetDbContextFromLocator(locator, typeof (T)) as T;
        }

        public static T GetByInterface<T>(this IDbContextCollection collection) where T : class, IDbContext {
            return GetDbContextFromCollection(collection, typeof (T)) as T;
        }
    }

My main use case for DbContextScope in this context is to convert much of my request scoped handlers and dependent services, to singletons, as we no longer need to import a DbContext into the constructors, which made them essentially stateful.

Would there be a place for this setup in the DbContextScope project, and would you recommend a similar or different approach?

Working with Store Procedure and Transaction

Hi, I have issue while working with stored procedure
my stored procedure have update command, and after the execution, I tried to retrieve the updated record.
my code is like below

using (var dbContextScope = dbContextScopeFactory.CreateWithTransaction(IsolationLevel.Serializable))
{
	var vendorID = "12345";
	
	//in this function, it will run SP, and inside the SP will update the vendor document status
	result = VendorProvider.spRecalculateVendorDocument(vendorID); 

	//get vendor document
	//vendorDocument object still have old status
	vendorDocument = VendorProvider.GetVendorDocument(vendorID);

	//commit database CRUD
	//after commit the db, vendor document status is updated to new one
	await dbContextScope.SaveChangesAsync();
}

the problem is, the vendorDocument object still hold the old data, although after execute dbContextScope.savechange(). the value in database will be updated to new one.

Not Friendly with dynamic dbcontexts

We use database partitioning in our application which requires us to initiate dbcontexts with a specific connection string. Is there any way you can think of implementing support for this? I suppose just adding Get(string connectionstring) and initiating with the proper constructor would work. Do you see any issues with that implementation?

Also, wouldn't performance be better if the Get would be public TDbContext Get() where TDbContext : DbContext, new() for parameter-less constructors? It would prevent the need to use the Activator in that case.

Thanks.

DbContext lifetime beginning after user login

Hi,

In the demo of DbContextScope I see the DbContext is defined with a default constructor and a hardcoded Connection String. In my scenario, I have a Users database and depending on which user logs in, I want to connect them to a secondary DbContext using a different Connection String. This doesn't seem to be possible with DbContextScope with the current implementation.

What is a correct way to do this, and in lifecycle of an ASP.NET MVC application how can we make sure the secondary DbContext is instantiated only when the user is logged in?

Thanks!

Magic Scope

It's difficult to pin down just what this project is attempting to solve. You seem to have taken the approach of managing the lifetime of the context outside of the business transaction, and in doing so introduced some magic on top of what should be a simple unit of work.

Take the example listed as a basic service call:

public void MarkUserAsPremium(Guid userId)
{
    using (var dbContextScope = _dbContextScopeFactory.Create())
    {
        var user = _userRepository.Get(userId);
        user.IsPremiumUser = true;
        dbContextScope.SaveChanges();
    }
}

In the above example, its unclear what context the _userRepository will be ultimately using. It could be argued that it doesn't matter, because inject should be handling that properly, and I could even agree with that myself. Where it gets sticky is the call to dbContextScope.SaveChanges(). The repository is using a context that is hidden from the caller, but then the caller commits the transaction through a different interface. There is no consistency in that pattern and consists of behind the scenes magic. It's unclear to the caller what affects will occur when SaveChanges() are called.

How many contexts will be affected? How many changes will persist? How does the caller gracefully handle exceptions?

These problems persist when making a direct call through DbContexts as well.

public void SomeServiceMethod(Guid userId)
{
    using (var dbContextScope = _dbContextScopeFactory.Create())
    {
        var user = dbContextScope.DbContexts.Get<MyDbContext>.Set<User>.Find(userId);
        [...]
        dbContextScope.SaveChanges();
    }
}

This example seems to confound the situation even further. Here we explicitly get the context we want, but instead of calling SaveChanges on that instance, we call it on the scope (which contains all DbContexts. Just what side effects could occur is not obvious to the caller.

This seems to be counter to your statement

Your services must be in control of the business transaction boundary

Although you make an exception for handling the DBContext lifetime, which I agree with completely, I argue that the service no longer controls the transaction boundary. You could potentially make several unrelated business transactions under the same context without the safety of a clear unit of work.

In your blog, you mention this consequence

A service method must use the same DbContext instance throughout the duration of a business transaction. This is so that all the changes made to your persistent model are tracked and either committed to the underlying data store or rolled back in an atomic manner.

Although its perfectly OK to handle the lifetime of the DbContext outside of a single transaction, your code is calling SaveChanges on multiple DBContext instances which could potentially commit unwanted transactions.

Take the following example:

_service.TransferMoney(2000, account);
_service.WithdrawMoney(1200);

Let's say within the TransferMoney transaction, the code returns prior to calling SaveChanges() for whatever contrived reason we like, possibly some business rule or exception.

The client code then calls WithdrawMoney, and locally the DbContext believes it has enough funds to cover the transaction, so it succeeds until the call to SaveChanges() occurs.

At this point, one of several things could occur:

  1. The database throws an exception, at which point bubbles up the stack and reports that WithdrawMoney has thrown an exception. Since the problem didn't actually occur in this method, we are now stuck with an akward way to handle this scenario as the proper course of action can not be determined.
  2. The database does not throw an exception, and allows the overdraft of funds, leaving the account with -800 remaining.
  3. Depending on the internal implementation of the two methods, it may actually persist both transactions, even if it should not have persisted the first one.

Obviously, the correct approach would be to send both transactions to the same service method as follows:

var transactions = new List<Transaction>(){
    new TransferMoneyTransaction(2000, account),
    new WithdrawMoneyTransaction(1200)
};
_service.Commit(transactions);

In this instance, one would only need a single unit of work within that service method. Which brings me back to the question, "What does this project solve?"

If one needs to reuse the DbContext across multiple service methods, that means the caller is now in control of business transactions outside of the service itself, which tells me those would be better served by wrapping them into their own service method.

I mean this as constructive criticism, and I'm only looking for your thoughts on the proper use case. In your article you clearly state

There is of course no such thing as one-size-fits-all

and go on to details the pros/cons of each approach. However, you didn't list the pros/cons of your own approach.

Synchronizing Model State to Database

Hi, this is more of a question than an issue, but this seems to be the best place to post. Feel free to close/move elsewhere if needed.

I'm wondering how you handle cases where EF's model state becomes out of sync with the database's state. Consider a basic user permissions structure where a user can have many roles, and roles have many permissions. Let's say you have a service that adds a permission to a role, and a service that removes a permission from a role. Now let's say that you want to determine what users will have their permissions changed by the addition or removal of a permission to a role. There are too many users to load them all into memory for the role in question, so you have to perform a database query to determine what users will be impacted, then do the update. However, what happens if the service is called from another service that also changed role permissions? Now you have pending database changes that will cause your query to return invalid results. With a normal dbcontext, you can just save to sync EF's model state to the database. However, with dbContextScope, you don't know if and when your changes will be synced since you could always be in a nested scope.

This example may be a little contrived for the purposes of forming a question, but I'm curious to hear how others are dealing with query, update, re-query workflows. For now, our team is changing our save behavior to be eager instead of lazy. We're also creating a transaction with the parent dbcontextscope and committing the transaction when the parent scope is saved. This gives us the rollback behavior of normal DbContextScope with the control of allowing our models to be kept in sync.

IoC containers support

Simple Injector fails with exception:
For the container to be able to create DbContextReadOnlyScope, it should contain exactly one public constructor, but it has 3.

Concurrency-Exception-Handling fails

Situation:
Pseudo-Code for handling Concurrency-Exception
using(testScope = ...)
{
try
{
repository.Update(projekt);
testScope.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}
testScope.SaveChanges(); //Retry to update Fails, because DbContextCollection says You can't call Commit() or Rollback() more than once on a DbContextCollection.
}

What happens in DbContextCollection.cs "Commit"-method:

115 foreach (var dbContext in _initializedDbContexts.Values)
116 {
117 try
118 {
119 if (!_readOnly)
120 {
121 c += dbContext.SaveChanges();
122 }
123
124 // If we've started an explicit database transaction, time to commit it now.
125 var tran = GetValueOrDefault(_transactions, dbContext);
126 if (tran != null)
127 {
128 tran.Commit();
129 tran.Dispose();
130 }
131 }
132 catch (Exception e)
133 {
134 lastError = ExceptionDispatchInfo.Capture(e);
135 }
136 }
137

138 transactions.Clear();
139 completed = true; // *!!! in case of an exception this ist wrong. This Statement should be placed in line 130. *

Consider renaming assemblies to follow Microsoft guidelines

This is related to #2

Microsoft's naming guidelines suggest using a format similar to

<Company>.<Component>.dll

when creating assemblies. The current structure of this project doesn't really work for that, as you've separated the interfaces and implementation into two projects. So, I would recommend a two step modification:

  1. Combine the implementation and interface projects, as you're not really gaining anything by having them split, and
  2. Renaming the project to something like Mehdime.Entity.

I can actually do both of these myself on a fork and submit a pull request, if you prefer. Once that is done, I can compile a single .dll for the NuGet package.

Obviously, this would be a breaking change for anyone using the existing code.

Recreating DbContext for better performance

Hello,

thank you very much for the DbContextScope!. I was looking for something like this to properly handling my DbContexts.

The only thing I'm missing at the moment is the ability to recreate a particular DbContext, because when I'm making a lot of inserts, the change tracker has to keep track of a lot of entities and I get better performance recreating the context.

So, I have added this functionality in the DbContextCollection class (and in the IDbContextCollection interface):

   public TDbContext GetNew<TDbContext>() where TDbContext : DbContext
    {
        var requestedType = typeof(TDbContext);

        // if the this context type wasn't created, create it using the Get method
        if (!_initializedDbContexts.ContainsKey(requestedType)) {
            return Get<TDbContext>();
        } else {
            // otherwise, we have to dispose and recreate this context type
            var dbContext = _initializedDbContexts[requestedType] as TDbContext;
            try {
                dbContext.Dispose();
            } catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e);
            }
            _initializedDbContexts.Remove(requestedType);

            return Get<TDbContext>();
        }
    }

I hope you find it useful and include it in your code.

Need way to disable disposing of DbContext when root DbContextScope is disposed

The way this library works now is that the DbContext instances are disposed when the root DbContextScope is disposed.

I'm using this library in an OData Web Api project. The behaviour of disposing DbContext instances is causing problems with the OData pipeline because OData expects the DbContext to be open until very late in the Web Api pipeline. The only way of keeping the DbContext open is to create the DbContextScope very early in the process in the Owin middleware, but I didn't want to do that because I want to have a readonly or readwrite scope depending on the requested controller action, and this is not yet known at the Owin stage.

So I had to resort to trickery to keep the DbContext from being disposed right away, which was to override the Dispose(bool disposing) method of the DbContext and add another ManualDispose() method to dispose of the DbContext at a later time.

It would be nice if it were possible to create a DbContextScope with the option to disable auto disposing of the DbContext instances.

Or does someone have another suggestion to tackle this issue?

nested IDbContextFactory.CreateWithTransaction

Why it's not possible to have some kind of nested transactions with nested scopes created with IDbContextFactory.CreateWithTransaction?

https://github.com/mehdime/DbContextScope/blob/master/Mehdime.Entity/Implementations/DbContextScope.cs#L43

I have several entities that create a scope with CreateWithTransaction because each of them should be transactional, but I also need to compose them and they (the inners) should not be dependent on each other (the outers) about creating a transaction.

I'm not doing the right approach?

Using ninject IoC with DbContextScope

I have a problem using ninject as IoC Container.

I get following error message:

Es ist ein Fehler in der Applikation aufgetreten. Die Entwickler wurden darüber benachrichtigt. Exception Message: Fehler beim Erstellen eines Controllers vom Typ "MyController". Vergewissern Sie sich, dass der Controller einen öffentlichen Konstruktor ohne Parameter besitzt.

This is my ninject Configuration:

        Bind<IDbContextScopeFactory>().To<DbContextScopeFactory>().InSingletonScope();
        Bind<IAmbientDbContextLocator>().To<AmbientDbContextLocator>().InSingletonScope();

Support EF7 in DbContextScope

Hi, i tryed changing Entity Framework 6 to EF 7, and compile time errors showed, is there a posiiblity to support EF 7 in the near future, also i will give it a try, to see if its simple or not to fix these errors.

Regards.

transactions

I'm trying to use your code with a CreateWithTransaction context scope, but I don't know how to make it work. Can you provide an example?

Having a Default DbContextFactory

Maybe it would be nice to have a Default DbContextFactory, that gives the client the possibility to set the connection string for projects that have multiple DBs.

namespace Mehdime.Entity
{
    public class DbContextFactoryDefault : IDbContextFactory
    {
        string _connection;
        public DbContextFactoryDefault(string connection_)
        {
            _connection = connection_;
        }

        public TDbContext CreateDbContext<TDbContext>() where TDbContext : DbContext
        {
            object[] arguments = new object[1] { (object)_connection };

            return (TDbContext)Activator.CreateInstance(typeof(TDbContext), arguments);
        }
    }
}

Use:

Dim dbContextScopeFactory = New DbContextScopeFactory(New DbContextFactoryDefault("testCon"))
Dim ambientDbContextLocator = New AmbientDbContextLocator()

Regards.

Best practice for taking advantage of EF first-level caching in Domain Service Layer.

Part of the appeal of using EF as opposed to a micro-ORM like Dapper is the first-level caching (to my knowledge, Dapper doesn't do this).

However, by placing the DbContextScope (or any Unit of Work style pattern) in my domain service layer methods, acting as the business transaction boundary, I'm not sure how to take advantage of EF's caching.

For example, consider the following interface:

public interface IOrderService
{
    Order Get(int orderId);
    void MarkOrderApproved(Order order, User user);
}

Imagine I then have a controller action processing a request to mark an order approved. It receives the orderId and I have the userId from the authenticated user making the call. However, I don't have the entities yet, and my domain service contract wants those entities. Thus:

public class OrderController
{
    public IActionResult MarkOrderApproved(int orderId)
    {
        var order = orderService.Get(orderId);
        var user = userService.Get(User.Id); //However this works.

        orderService.MarkOrderApproved(order, user);

        return Ok();
    }
}

What's the best practice here? Is it to not write my Domain Service methods to accept entities, and allow each method to do whatever lookups inside the scope? That would allow it take advantage of the first-level cache, and my code becomes:

public class OrderController
{
    public IActionResult MarkOrderApproved(int orderId)
    {
        orderService.MarkOrderApproved(orderId, User.Id);
        return Ok();
    }
}

and

public class OrderService : IOrderService
{
    void MarkOrderApproved(int orderId, int userId)
    {
        using (var dbContextScope = dbContextScopeFactory.Create())
        {
            var order = orderRepository.Get(orderId);
            var user = userRepository.Get(userId);

            order.Status = OrderStatus.Approved;

            dbContextScope.SaveChanges();
        }
    }
}

This seems like a clean solution, but it restricts my domain service layer from accepting domain entities as parameters so that they may be looked up within the internal scope.

Should I offer overloads on my domain service interface, like:

public interface IOrderService
{
    void MarkOrderApproved(int orderId, int userId);
    void MarkOrderApproved(Order order, User user);
}

This seems dirty to me, but I'm curious what the best practice is for taking advantage of the first level caching while not making my domain service layer suffer.

Is there another option that I'm missing outside of method injection of the DbContext (which this library is meant to solve)?

EDIT
Some sites seem to suggest that domain services should only accept primitives, enums, structs, and DTOs as arguments to their methods.

DDD seems to suggest that they should only accept Domain Objects, and that ORM entities are DTOs that should be mapped to Domain Objects before being passed to the domain service layer.

To me this indicates that any transactions should occur outside of domain services, at the application service layer exclusively. Domain services would be ignorant of transactions.

Thanks.

Not Saving Changes

I feel like I'm doing this wrong, but for some reason I can't seem to SaveChanges properly.

using (var dbContextScope = _dbContextScopeFactory.Create())
{
    var context = dbContextScope.DbContexts.Get<ApplicationContext>();

    var file = context.Set<Models.File>().Find(id);

    file.Name = "This should be updated, but it's not :)";

    var result = dbContextScope.SaveChanges();
}

The only way I'm able to actually get the result to be > 0 is to create one of these _dbContextScopeFactory.CreateWithTransaction(IsolationLevel.Serializable)

My creates work perfectly, but for some reason the updates don't seem to update 😕

Am I going about this the wrong way?

ReadOnly and Create Context in same service?

Is there a pattern which allows for a Service class to handle both read and write operations? Im trying to retrofit our current service layer (no repo layer) and we do read/write operations in the same class.

If I use a single IDbContextScopeFactory object, it will throw an exceptionCannot nest a read/write DbContextScope within a read-only DbContextScope

I dont want to have to create two service classes, just to handle read or write operations, is there away around this? If its solely a scoping issue, perhaps i can somehow design the layer in a way that will have separate scopes for each operation type?

Any guidance would be very helpfull!

Simple Injector - Injecting IDbContextScopeFactory

I'm trying to inject a IDbContextScopeFactory object using Simple Injector but I'm always getting the following error:

Additional information: The configuration is invalid. Creating the instance for type IDbContextScopeFactory failed. The constructor of type DbContextScopeFactory contains the parameter with name 'dbContextFactory' and type IDbContextFactory that is not registered. Please ensure IDbContextFactory is registered, or change the constructor of DbContextScopeFactory.

My problem is that I dont see an implementation of IDbContextFactory anywhere so I'm a little lost on how to resolve this situation. Any help is appreciated

Unable to use a non-interfaced DbContext with DbContextScope

I am using .NET Core 1.1 and EF Core, in which my MyDbContext simply inherits from EntityFrameworkCore.DbContext. Unfortunately, DbContextScope expects only an EntityFramework.DbContextScope.IDbContext. How do I resolve this?

I tried implementing the OnConfiguring method in MyDbContext and manually provided the connection string, and while this does get it working, I don't like having to provide the connection string inside there since it's being handled by .NET Core's Startup.cs already:

services.AddDbContext<MyDbContext>(options => options.UseSqlServer("connection string here"));

Support EF 7

Hi. are there any plans to support EF 7 and .NET Core?

DbContext Custom Connection String

Hello Mehdi, I would like to thank/congratulate you for this nice dll and post.

I am using in a business application and it works like charm, however I have a requirement that I cannot store connectionStrings in the app/web.config. So I need to set it programmatically.

The GetContext() method initializes the context object with the correct connectionString however in the Repository.Insert() the ambientLocator returns a context object without a connection string and throws
InvalidOperationException "No connection string named 'BDAL_DemoEntities' could be found in the application config file."

It seems like it instantiates a new context object, is there a way to solve the issue?

 // Calling method
 using (var scope = ContextFactory.ScopeFactory.Create())
        {
            using (var context = GetContext()) // Here the context.Database.Connection is correct
            {
                EFType myObject = this.ToEF();//Get an EF Object 
                myObject = Repository.Insert(myObject);
            }
        }

    public BDAL_DemoEntities GetContext()
    {
        string connStr = "metadata=res://*/Model.BDAL_DemoModel.csdl|res://*/Model.BDAL_DemoModel.ssdl|res://*/Model.BDAL_DemoModel.msl;provider=System.Data.SqlClient;provider connection string=\"data source=.;initial catalog=BDAL_Demo;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework\"";

       BDAL_DemoEntities cntxt = new BDAL_DemoEntities(connStr);
       return cntxt;

        // To use the default connection string from app/web.config 
        return new BDAL_DemoEntities();
    }

    // The issue is in the Repository.Insert(). The ambientContextLocator
    // returns a context that throws an exception as there is no connection String in the app.config
    var context = _ambientDbContextLocator.Get<context>();

How to mock and unit test?

Hi, this is not an 'issue' per se but I just want to know how do I mock this so that I can add unit test?
I have FakeDbSet and FakeDbContext but I could not find a way to actually inject this into DbContextScope without major changes to the source code..

Any help is appreciated... thanks.

Nuget Package?

Just wondering if you have thought about publishing this as a Nuget Package?

signing assembly

Hey @tiesont and @mehdime, I'd like to sign the assembly because I'm prevented from using it in one of my projects because it's not strongly named. We obviously don't want to commit a private signature key to the repo. If you guys will sign the assembly then that's great otherwise can you give me access in Nuget and I can sign the latest one then Share the signing key among us (through email, dropbox, drive, or however we agree to share the key).

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.