|
I've never worked with concurrency in SQL before.
I'm working on a WPF app hitting SQL through a Web API.
What's the right way to handle a concurrency violation? Do I need to check the timestamp myself in my DAL's update methods? Or will SQL throw an exception? If I have to check it myself, is throwing an exception the best way? What exception(s) are used for this?
What I'm really interested in here is the full workflow from the time the user clicks Save to either the data is saved or a violation is handled in the front end?
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
A DBConcurrencyException[^] is thrown. This[^] shows how it is handled.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Thanks.
Seems to me that after catching the DBConcurrencyException the only choice is to notify the user and reload the record.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Yes, since you do not know wheter the old record has been modified, or even still there. Would obviously not be happening often, since mostly there's not a lot of people working on the same record at the same moment.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Kevin Marois wrote: I've never worked with concurrency in SQL before.
What makes you think that the business (not technology) needs of the business will lead to a situation where, for whatever business reason, two updates might occur on the same record?
Note that I using "business" very specifically in the above. I am not referring to hypothetical scenarios.
And in general modern databases themselves do not have "concurrency" issues.
|
|
|
|
|
I've read the docs and it seems that processes writing to a single log file requires socket implementation. Really? is it not possible to create a static singelton class and logger instance, in a module, and import that single instance object into each module as the logger and use that? In either case, how might this be done simply and without extravagance.
|
|
|
|
|
"Static" or singleton have boundaries in which they work, in these cases the applications themselves. To do it simply, use the "Debug.WriteLine" methods. To see the log, simply attach a debugger.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Hi everybody. I have a question about Memento pattern.
Let's suppose we have a class which's state has to be saved and later restored, and we resorted to the Memento pattern for that.
What if the state includes resources that have to be explicitly released (like file handles, OpenGL textures etc)?
Should I make them part of the saved state? This necessitates to handle memento objects in a special manner: if memento was restored, then it's up to the originator class to handle the resources, if memento is dropped, then it has to clean up itself. Pretty entangled logic.
How would you implement Memento when state has resources to be released?
Should I apply Memento at all when object state includes OS resources that have to be released?
|
|
|
|
|
Member 13897152 wrote: What if the state includes resources that have to be explicitly released (like file handles, OpenGL textures etc)? I don't think it's a good idea to keep such things in a class that needs to be saved, since they will not be valid on restore.
|
|
|
|
|
You "save" things that may change. You don't simply save "everything" related to an object instance; things like "resources" are usually "common" to the class / assembly and are not "saved" for each object.
"Saving" is independent of any "cleaning up" you do "after" saving (key data).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Member 13897152 wrote: How would you implement Memento when state has resources to be released? Not; the originator has to release those - the memento itself is just there to hold an internal state.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Keep in mind that a resource that needs to be released is, by definition, an object, and is therefore tracked by your object as a memory reference.
This should inform the design decisions made on your originator. Do not use handles to track files, use paths. Do not load a texture into the originator; apply a method for locating a texture based on a primitive type. Don't contain streams in the originator, instead contain values that will help re-initialize them.
A lot of these issues are a big part of the reason why Model classes and MVC-like patterns have come into such heavy use in recent years.
"Never attribute to malice that which can be explained by stupidity."
- Hanlon's Razor
|
|
|
|
|
So I have this design in Python2.7. Basically it is an EPG app that can read EPG programme events from 1 or more XMLTV sources. I would like to be able to use a generic code base and switch-in the XMLTV parsing code. For example, in 'C' I can use:
epg.c:
#ifdef _XMLTV_rytec
#include ./xmltv/rytec.h
#endif
#ifdef _XMLTTV_bbc
#include ./xmltv/bbc.h
#endif
...
...
load_xmltv()
...
... So what i can do here is define the preprocessor macros (_XMLTV_*) at make time, use the compiler directives to pull in the appropriate definitions for the desired xmltv parser, and switch in the corresponding source/object module (rytec.c/rytec.o and bbc.c/bbc.o) using the Makefile. Here for example, if XMLTV is not defined outside the Makefile at build (i.e. command line option) then the default rytec module is built in.
Makefile:
..
XMLTV_OBJS = ./src/xmltv/rytec.o
EPG_OBJS = epg.o $(XMLTV_OBJS)
..
obj/%.o:%.c
gcc -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
epg: $(EPG_OBJS) \
gcc -o $@ $(CFLAGS) $(EPG_OBJS) $(LDFLAGS) $(LDLIBS)
.. How can I achieve the same thing in Python please?
modified 3-Jul-18 6:27am.
|
|
|
|
|
if XMLTV = 'something':
import xmltva
else:
import xmltvb
|
|
|
|
|
you're kidding!! that easy. Well, i tried and it the interpreter complains about XMLTV not being set. So on my linux box...
XMLTV='bbc' python test.py
It's not picking up the XMLTV but i bet there is a way to get this from the OS shell ?? I'll search..
**EDIT**:
if os.environ['XMLTV'] == 'bbc':
import xmltv.bbc PERFECT! works a treat.
My god this Python is simple it's actually quite hard to learn coming from such a typesafe statically synataxically tight langauge as C !!
modified 3-Jul-18 9:37am.
|
|
|
|
|
Remember, Python is interpreted, not compiled and linked, so the mechanics of it are quite different from C/C++ etc.
|
|
|
|
|
agreed... I'm getting there
and Richard
this time
THANKS
|
|
|
|
|
Appreciated; happy to help.
|
|
|
|
|
I'm starting a new project. I've always used Linq-to-SQL. This time I'm going to use EF and the Repository pattern. Also, I'm really new to Web API's, so if I made a mistake, please let me know.
So I spent the last few days researching EF and the Repository Pattern/Unit of Work. I understand the Unit of Work concept and that EF is by design a Unit of Work. Having said that, here is what I've come up with. I'd like your opinion.
Repository Interface
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
Repository Base Class
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContext Context { get; private set; }
public Repository(DbContext context)
{
Context = context;
}
public TEntity Get(int id)
{
return Context.Set<TEntity>().Find(id);
}
public void Add(TEntity entity)
{
Context.Set<TEntity>().Add(entity);
}
}
Projects Interface and Repository
This class allows me to add specialized project-related data functions.
public interface IProjectsRepository : IRepository<Project>
{
IEnumerable<Project> FindProjectsByName(string name);
}
public class ProjectsRepository : Repository<Project>, IProjectsRepository
{
FalconContext _context;
public ProjectsRepository(FalconContext context)
: base(context)
{
_context = context;
}
public IEnumerable<Project> FindProjectsByName(string name)
{
Expression<Func<Project, bool>> nameFilter = e => e.ProjectName.Contains(name);
return Find(nameFilter);
}
}
Biz Layer
This class is the only class that knows about the data later. The controllers all call into here. That allows me to apply business logic in true Units of Work:
public class BizObject : IBizObject
{
private IProjectsRepository projectsRepository;
public void AddProject(Project entity)
{
using (var dc = new FalconContext())
{
var projectRepo = new ProjectsRepository(dc);
var projectTaskRepo = new ProjectsTaskRepository(dc);
var test = projectRepo.FindProjectsByName(entity.ProjectName);
if (test != null)
{
projectRepo.Add(entity);
foreach (var task in entity.Tasks)
{
projectTaskRepo.Add(task);
}
dc.SaveChanges();
}
else
{
throw new DuplicateProjectException(entity.ProjectName);
}
}
}
}
Controller
public class ProjectsController : ApiController
{
private IBizObject _bo;
public IHttpActionResult AddProject(Project entity)
{
_bo = new BizObject();
_bo.AddProject(entity);
return Ok();
}
}
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Kevin Marois wrote:
var test = projectRepo.FindProjectsByName(entity.ProjectName);
if (test != null)
{
projectRepo.Add(entity);
foreach (var task in entity.Tasks)
{
projectTaskRepo.Add(task);
}
dc.SaveChanges();
}
else
{
throw new DuplicateProjectException(entity.ProjectName);
}
If you've implemented it properly, FindProjectsByName will never return null .
It would also be very odd for that method to return null if there were matching projects, and not-null if there weren't.
Perhaps you mean something more like:
var test = projectRepo.FindProjectsByName(entity.ProjectName);
if (test.Any()) throw new DuplicateProjectException(entity.ProjectName);
projectRepo.Add(entity);
foreach (var task in entity.Tasks)
{
projectTaskRepo.Add(task);
}
dc.SaveChanges();
Kevin Marois wrote:
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
Purists frown on it, but I generally think it makes more sense to return IQueryable from methods like this. Otherwise, you end up having to provide overloads for every possible combination of operations you need to use - sorting, paging, searching, etc.
The objection is usually that returning IQueryable lets the code that uses the repository turn a simple query into something heavy and convoluted, which degrades the performance. But returning IEnumerable involves loading the entire table into memory, which could also degrade the performance. And if you're using lazy-loading, you could still end up with the "Select N+1" problem, where accessing a property on the returned object issues a new database call.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Points well taken. Thanks for looking it over.
Richard Deeming wrote: Purists frown on it,
So I've heard.
What I gather is that if you return an IQueryable you'll sooner or later end up with queries in places OTHER than your data layer. Should you need that, then create a method on the DAL to handle it. I tend to agree with your point as well as the research I saw, so I don't really have a preference.
Other than that, would you say my overall design is solid?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I think there's still room for improvement.
Your classes are currently tied to specific implementations, which would make it harder to test them.
Perhaps try something like this:
interface IUnitOfWork : IDisposable
{
void Save();
Task SaveAsync();
}
class FalconContextUnitOfWork : IUnitOfWork
{
private readonly FalconContext _context;
public FalconContextUnitOfWork(FalconContext context)
{
_context = context;
}
public void Save()
{
_context.SaveChanges();
}
public Task SaveAsync()
{
return _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
}
interface IBizObject : IDisposable
{
void AddProject(Project entity);
}
class BizObject : IBizObject
{
private readonly IProjectsRepository _projectsRepository;
private readonly IProjectsTaskRepository _projectsTaskRepository;
private readonly IUnitOfWork _unitOfWork;
public BizObject(IProjectsRepository projectsRepository, IProjectsTaskRepository projectsTaskRepository, IUnitOfWork unitOfWork)
{
_projectsRepository = projectsRepository;
_projectsTaskRepository = projectsTaskRepository;
_unitOfWork = _unitOfWork;
}
public void AddProject(Project entity)
{
if (_projectsRepository.FindProjectsByName(entity.ProjectName).Any())
{
throw new DuplicateProjectException(entity.ProjectName);
}
_projectsRepository.Add(entity);
foreach (var task in entity.Tasks)
{
_projectsTaskRepository.Add(task);
}
_unitOfWork.Save();
}
public void Dispose()
{
_unitOfWork.Dispose();
}
}
public class ProjectsController : ApiController
{
private IBizObject _bo;
public ProjectsController(IBizObject bo)
{
_bo = bo;
}
public IHttpActionResult AddProject(Project entity)
{
_bo.AddProject(entity);
return Ok();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing) _bo.Dispose();
}
}
Register all of the concrete implementations as transient services in your DI container. You should then get a new instance of all three classes for each request, but sharing the same instance of your DbContext between them.
In your unit tests, you can pass specific mocks of the interfaces to the constructor of the class you're testing.
Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Docs[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I see. I think I have it
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Richard Deeming wrote: Register all of the concrete implementations as transient services in your DI container
I think I need you to explain this some more.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|