Add auto generated field and value to database

asp.net-mvc entity-framework entity-framework-core

Question

I am working on a program whereby I need to add an auto generated field and value to my database. So to put it in context, I have a program where I can do normal CRUD operations and this is connected using swagger. I have a vouchers table where I want an auto generated text field which I have code for and I want to be able to enter an amount and it auto populates the fields in the database. The code is as follows:

My Voucher controller:

    [Route("[controller]")]
[ApiController]
public class VouchersController : ControllerBase
{
    private readonly ComicStockContext _context;

    private IVoucherService _voucherService;

    public VouchersController(ComicStockContext context, IVoucherService voucherService)
    {
        _context = context;
        _voucherService = voucherService;
    }

    // GET: api/Vouchers
    [HttpGet]
    public IEnumerable<Vouchers> GetAllVouchers([FromQuery] int page)
    {
        return _voucherService.GetAllVouchers(page);
    }

    [HttpGet("generate")]
    // code to insert amount and generated string needs to go here

My interface for vouchers service:

    namespace BusinessLogic.ServicesInterfaces
{
    public  interface IVoucherService
    {
        IEnumerable<Vouchers> GetAllVouchers(int page);

        Vouchers FindVoucherByID(int voucherID);

        void InsertVoucher(Vouchers vouchers);


    }
}

My Vouchers Service

    public class VoucherService: IVoucherService
{
    private IVoucherRepository _voucherRepository;

    public VoucherService(IVoucherRepository voucherRepository)
    {
        _voucherRepository = voucherRepository;
    }


    public IEnumerable<Vouchers> GetAllVouchers(int page)
    {
        return _voucherRepository.GetAllVouchers(page);
    }

    public Vouchers FindVoucherByID(int voucherID)
    {
        return _voucherRepository.FindVoucherByID(voucherID);
    }

    public void InsertVoucher(Vouchers vouchers)
    {
        _voucherRepository.InsertVoucher(vouchers);
    }

    public void InsertGeneratedVoucher(string vouchercode, int amount)
    {
         String GetVoucherNumber()
        {
            int size = 20;
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }

            return builder.ToString();
        }
        vouchercode = GetVoucherNumber();
        //_voucherRepository.InsertGeneratedVoucher(vouchercode, amount);
    }
}

My Vouchers Repository

    public class VoucherRepository: GenericRepository<Vouchers>, IVoucherRepository
{
    public VoucherRepository(): base()
    {
    }

    public VoucherRepository(ComicStockContext comicStockContext) : base(comicStockContext)
    {
    }

    public Vouchers FindVoucherByID(int voucherID)
    {
        return GetById(voucherID);
    }

    public IEnumerable<Vouchers> GetAllVouchers(int page)
    {
        return GetAll(page);
    }

    public void InsertVoucher(Vouchers vouchers)
    {
        Insert(vouchers);
    }
}
}

My Interface for voucher repository

{
public interface IVoucherRepository
{
    IEnumerable<Vouchers> GetAllVouchers(int page);

    Vouchers FindVoucherByID(int voucherID);

    void InsertVoucher(Vouchers vouchers);

And my generic base repository

{
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    protected ComicStockContext _context = null;
    protected DbSet<T> table = null;

    public GenericRepository()
    {
        this._context = new ComicStockContext();
        table = _context.Set<T>();
    }

    public GenericRepository(ComicStockContext context)
    {
        _context = context;
        table = _context.Set<T>();
    }

    public IEnumerable<T> GetAll(int page)
    {
        return table.ToList().Skip(25 * page).Take(25);
    }
    public T GetById(object id)
    {
        return table.Find(id);
    }
    public void Insert(T obj)
    {
        table.Add(obj);
        Save();
    }
    public void Update(T obj)
    {
        table.Attach(obj);
        _context.Entry(obj).State = EntityState.Modified;
        Save();
    }
    public void Delete(object id)
    {
        T existing = table.Find(id);
        table.Remove(existing);
    }
    public void Save()
    {
        _context.SaveChanges();
    }



}
}

As well as the interface for the generic repository

    public interface IGenericRepository<T> where T : class
{
    IEnumerable<T> GetAll(int page);
    T GetById(object id);
    void Insert(T obj);
    void Update(T obj);
    void Delete(object id);
    void Save();
}

So basically the code which I am trying to achieve is, I must be able to insert an amount using swagger, for example $100 and it must insert the $100 in my vouchers table along with an auto generated string, and the rest of the fields should just populate as Null.

1
1
2/17/2020 8:20:13 AM

Accepted Answer

You've got the method to generate your voucher code, good or bad, so where is the problem? Is this a framework that someone else laid out that you don't quite understand yet because while generic repository patterns like this are rather anemic, from what I can see your code is 90% there:

public void InsertGeneratedVoucher(int amount)
{
    // TODO: Assert that your Amount is valid.. For instance can it be 0? <0??

    string GetVoucherNumber()
    {
        int size = 20;
        StringBuilder builder = new StringBuilder();
        Random random = new Random();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
            builder.Append(ch);
        }
        // TODO: Check for duplicates?
        return builder.ToString();
    }
    var voucher = new Vouchers
    {
        Vouchercode = GetVoucherNumber();
        Amount = amount; 
    };
    _voucherRepository.Insert(voucher);
}

There is no point accepting a VoucherCode if you want this method to generate a new one. If you want to return it, use a return value on the method. If you can accept a voucher code from the caller then it should be validated to check for duplicates and that it is valid etc. All arguments to a method should be asserted/validated. The method to build a voucher number should probably be moved out to a separate utility method, and you should consider adding a check for duplicate voucher numbers once one is generated. A simpler alternative would be Guid.New().ToString("N") will provide a effective "random" 32 character code. Truncating it to 20 characters will weaken it but it avoids easily confused letters (0 vs O).

The only other thing is that your service should ensure that all required fields (non-null-able) for this new voucher are either provided as parameters or generated within this method.

1
2/17/2020 1:32:27 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow