How to ensure unique column value inside code? - database

I am learning ASP.NET MVC, and confused as to how can I ensure unique values for columns (username & email) for a table.
Can anybody help me with a sample code or a link to the tutorial which shows & explains this?
EDIT:
I know that I can apply an unique key constraint on my table columns and achieve it. However, I want to know how can I achieve it via ASP.NET MVC code?
UPDATE:
I wish to do a check in my application such that no duplicated values are passed to DAL, i.e. achieve a check before inserting a new row.

Mliya, this is something you are controlling at the database level, not at the application level.
If you are designing a database with a users table in which you would like to constraint the username and email columns to be UNIQUE you should create a UNIQUE INDEX on such columns.
without knowing your backend database (mySQL, SQL Server, MS Access, Oracle...) it's not the case to show you pictures or tell much more, just create the table with the designer and add these unique constraints to those columns and by design you will be sure no duplicated values will ever be inserted for username and email.
I also suggest you to create an ID column which would be set as PK (primary key, which means it will be automatically set as NON NULL and UNIQUE).
From your ASP.NET MVC application you should of course make sure that no duplicated values are then passed to the DAL for username and email. You could do this in different ways, the easiest is probably to check before inserting a new row if any user already exists with that username and/or email and if so you can show a notification message telling the user to please select another pair of values.

In an ASP.NET MVC architecture, you should try to do most of your validation in the Model, but with low-level validation rules like these, it's sometimes impossible. What you should look to for answers then is Domain-driven Design (DDD) where Application Services can solve such low-level needs.
Application Services will have access to the database (either directly, or better yet; indirectly through repositories) and can perform low-level validation and throw ValidationException or something similar (with detailed information the Controller can act upon and respond to the user) when a prerequisite or business rule isn't met.
S#arp Architecture implementes all of this in a best-practice framework that you can use as a basis for your ASP.NET MVC applications. It is highly opinionated towards DDD principles and NHibernate, and it will sometimes force your hand on how you do stuff, which is kind of the point. The most important part about it is that it learns you how to deal with these kinds of problems.
To answer your question more concretely and in the spirit of DDD, this is how I would solve it:
public class UserController
{
private readonly IUserService userService;
public UserController(IUserService userService)
{
// The IUserService will be injected into the controller with
// an "Inversion of Control" container like NInject, Castle Windsor
// or StructureMap:
this.userService = userService;
}
public ActionResult Save(UserFormModel userFormModel)
{
if (userFormModel.IsValid)
{
try
{
// Mapping can be performed by AutoMapper or some similar library
UserDto userDto = Mapper.Map<UserDto>(userFormModel);
this.userService.Save(userDto);
}
catch (ValidationException ve)
{
ViewBag.Error = ve.Detail;
}
}
// Show validation errors or redirect to a "user saved" page.
}
}
public class UserService : IUserService
{
private readonly IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
// The IUserRepository will be injected into the service with
// an "Inversion of Control" container like NInject, Castle Windsor
// or StructureMap:
this.userRepository = userReposityr;
}
public UserDto Save(UserDto userDto)
{
using (this.userRepository.BeginTransaction())
{
if (!this.userRepository.IsUnique(userDto.UserName))
{
// The UserNameNotUniqueValidationException will inherit from ValidationException
// and build a Detail object that contains information that can be presented to
// a user.
throw new UserNameNotUniqueValidationException(userDto.UserName);
}
userDto = this.userRepository.Save(userDto);
this.userRepository.CommitTransaction();
return userDto;
}
}
}

Related

How to set the BAccount to updated so that sales force integration picks up that there was a update

Good day
The SalesForce feature that can be enabled under licensing(Enable/Disable Features) integrates with SalesForce. It picked up that there was a change in the Business Account and sets the account to Modified locally(This can be seen in a new Tab in the Business Account).
I created a new field UsrCreditLimit in the BAccount. This is to move the Credit limit to the Business account so that the standard SalesForce integration can see the field.
The problem I have is when I update the field the SalesForce code to trigger the sync doesn't happen; The Field changes but the sync doesn't happen.
I have tested if I manually change the field the code does execute to trigger the sync. I have also tried opening a new Graph in the code to update the field without any luck.
Is there a way to set the BAaccount to Updated using the SalesForce dll/code.
namespace PX.Objects.AR
{
public class CustomerMaint_Extension : PXGraphExtension<CustomerMaint>
{
#region Event Handlers
public delegate void PersistDelegate();
[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
Customer curCustomer = this.Base.CurrentCustomer.Select();
CR.BAccountExt curBAccountExt = curCustomer.GetExtension<CR.BAccountExt>();
curBAccountExt.UsrCreditLimit = curCustomer.CreditLimit.Value.ToString();
baseMethod();
}
}
}
Not sure if I understood your code correctly ...
Since a customer is a BAccount (it actually inherits from BAccount), why don't you also add your custom field to the Customer? and then it should be just a matter of updating this custom field. No need to call Save.PressButton again.

Handling server exceptions with Breeze SaveChanges () method

I am using Breeze with Angular and EF 6 in my project and I have a form where I perform CRUD operations.
I have this entity called: Car2Sale which is a many-to-many table (Id, CarId, SaleId). Id is the PK for this table while CardId and SaleId are FKs to their associated tables and they are grouped together in a unique index. (CarId, SaleId).
When I want to add a new Car2Sale entity with a CarId and SaleId that already exist in the database I get this error on server side: Violation of unique constraint... at this method:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle) {
return _repository.SaveChanges(saveBundle);
}
which is correct because I wanted to prevent the user from introducing similar keys in the same table.
On the client side I receive the error in the
entity.entityAspect.getValidationErrors();
and I display it using Toastr.js.
I was wondering what is the best practice to do exception handling in the SaveChanges() method in this case on the server side.
I was thinking about using a try catch on the server side and return a SaveResult of my own, like below:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle) {
SaveResult myResult = null;
try {
myResult = _repository.SaveChanges(saveBundle);
} catch(Exception ex) {
Logger.Log(ex.toString());
}
return myResult;
}
Many thanks
My main objection to your particular approach is that you're swallowing the error and returning what appears to be a "happy" SaveResult to the client. The BreezeJS client will assume that the save succeeded and will update your cached entities accordingly. That's not a good idea!
You can certainly catch it on the server-side and might want to do so in order to reshape the error response. I think that I would do so INSIDE the repository as I'm disinclined to have persistence logic in my controllers. Encapsulating that stuff is the raison d'etre of the repository/Unit-of-Work pattern.
It's not clear to me how this helps you on the client side. You still need to send the error to the client and have the client do something reasonable with it.
You might want to look at the Breeze Labs SaveErrorExtensions for ideas about interpreting errors on the client. To my mind, the hard thing is communicating actionable intelligence to the user. That's a business/design decision that we can't solve for you. We can give you the information; you have to make sense with it.
HTH.

How to load Entity Framework Self Track TrackableCollection<T> relationship data only when needed?

I use Entity Framework 4 and Self Tracking Entities. The schema is like:
Patient -> Examinations -> LeftPictures
-> RightPictures
So there is TrackableCollection of these two relationships Patient 1 - * ....Pictures.
Now when loading the customers Form and browsing the details I dont need to load these
data images, only when another form is loaded for Examination details!
I am using a class library as a Data Repository to get data from the database (SQL Server) and this code:
public List<Patient> GetAllPatients()
{
try
{
using (OptoEntities db = new OptoEntities())
{
List<Patient> list = db.Patients
.Include("Addresses")
.Include("PhoneNumbers")
.Include("Examinations").ToList();
list.ForEach(p =>
{
p.ChangeTracker.ChangeTrackingEnabled = true;
if (!p.Addresses.IsNull() &&
p.Addresses.Count > 0)
p.Addresses.ForEach(a => a.ChangeTracker.ChangeTrackingEnabled = true);
if (!p.PhoneNumbers.IsNull() &&
p.PhoneNumbers.Count > 0)
p.PhoneNumbers.ForEach(a => a.ChangeTracker.ChangeTrackingEnabled = true);
if (!p.Examinations.IsNull() &&
p.Examinations.Count > 0)
p.Examinations.ForEach(e =>
{
e.ChangeTracker.ChangeTrackingEnabled = true;
});
});
return list;
}
}
catch (Exception ex)
{
return new List<Patient>();
}
}
Now I need when calling the Examination details form to go and get all the Images for the Examination relationship (LeftEyePictures, RightEyePictures). I guess that is called Lazy Loading and I dont understood how to make it happen while I'm closing the Entities connection immidiately and I would like to stay like this.
I use BindingSource components through the application.
What is the best method to get the desired results?
Thank you.
Self tracking entities don't support lazy loading. Moreover lazy loading works only when entities are attached to live context. You don't need to close / dispose context immediately. In case of WinForms application context usually lives for longer time (you can follow one context per form or one context per presenter approach).
WinForms application is scenario for normal attached entities where all these features like lazy loading or change tracking work out of the box. STEs are supposed to be used in distributed systems where you need to serialize entity and pass it to another application (via web service call).

How ria services manage transactions

I learnt how can we configure transactions in Entity Framework using TransactionScope in one other question of mine. However it still confuses me! I mean how does RIA services execute transactions and how can we specify transaction options? I mean, suppose on the client in Silverlight we specify something like this :-
someContext.Add(someEntity1);
someContext.Add(someEntity2);
someContext.Add(someEntity3);
Now when i call someContext.SubmitChanges() this is going to call InsertSomeEntity() on the server in my domain service class. What is the guarantee that all three records will be inserted into the database and if one fails all of them fails? And how can we change these options?
Chand's link has a good example. WCF RIA will submit a ChangeSet for the SubmitChanges containing all 3 Add's. In your DomainService, you can override the PersistChanges method to complete the transaction.
public class SomeEntityDomainService : DomainService
{
SomeEFContext _someEFContext;
public SomeEntityDomainService()
{
_someEFContext = new SomeEFContext();
}
public void InsertSomeEntity(SomeEntity someEntity)
{
// Called 3 times in your example
_someEFContext.SomeEntities.Add(someEntity);
}
protected override bool PersistChangeSet()
{
// Called exactly once per SubmitChanges() in Silverlight
_someEFContext.SaveChanges();
}
}
All of this happens in one request from the client to the server, not 3 requests.

Silveright - extending AuthenticationService to provide custom authentication

I am trying to add to the authentication system provided in the Silverlight 4 business template as my model does not completely fit that provided in the template. I have an existing web service that performs my authentication and provides roles and also permitted operations for each role. This is the model provided by AzMan/Authentication Manager.
However, rather than just get a single role, following authentication I provide the user with a list of available roles and allow the user to select one of these roles and then get a list of operations/actions for that selected role.
The problem that I have is that I can't work out how to add new methods to the authenticationservice to allow me to get the operations for the current user, and currently selected role in order to complete the login process e.g.
public SessionInfo GetOperations(string username, string selectedRole)
{
SessionInfo sessionInfo;
using (AzManServiceClient azClient = new AzManServiceClient("AnonymousAuthentication"))
{
sessionInfo = azClient.LoginUserByUsername("msldap://CN=LiveApps,CN=Program Data,DC=HLSUK,DC=local", "AIRS", selectedRole, null, username);
}
return sessionInfo;
}
The above method is not accessible from the LoginForm.xaml.cs using WebContextBase.Current.Authentication... Only methods such as Login are visible which is even more baffling because I can't see these methods in authenticationbase. I'm completely confused. How do I add new methods to the authentication service, or should I create a new domainservice, or should I access the azman service to get the operations directly from the silverlight client.
Have you tried to Override the methods in AuthenticationBase?
Then you can expand your authenticationservice with whatever logic you want.
<EnableClientAccess()>
Public Class AuthenticationRiaService
Inherits AuthenticationBase(Of UserAccount)
Protected Overrides Function ValidateUser(ByVal userName As String, ByVal password As String) As Boolean
End Function
End Class
Also set
WebContext.Current.Authentication To your authenticationservice as found in namespace System.ServiceModel.DomainServices.Client.ApplicationServices
Sorry for stupid VB code. :D

Resources