Sunbro
Sunbro

Reputation: 5

MVC Save to two table

Project has got two tables. It takes a value from sensors to database. How can i save to two database with relationship ? Codes could be wrong. Maybe someone can help.

public class Assets
    {
        public int id { get; set; }
        public int? sensorid { get; set; }
        public int? value { get; set; }
        public DateTime? DateTime { get; set; }
        public virtual Sensors Sensors { get; set; }
    }

and

 public class Sensors
{
    public int id { get; set; }
    public int? sensorname { get; set; }
    public virtual ICollection<Assets> Assets { get; set; }
}

controller

 public ActionResult Index(Sensors sensors, Assets assets)
    {

        int[] response = client.ReadHoldingRegisters(StartAddress, quantity);
        client.Disconnect();
        Assets asst = new Assets();
        Sensors sns = new Sensors();

        for (int i = 0; i < quantity; i++)
        {
            asst.value = response[i];
            sns.id = StartAddress;
            db.Assets.Add(asst);
            for (int x = 0; x < 3; x++)
            {
                db.Sensors.Add(sns);

            }
            db.SaveChanges();
        }    

Upvotes: 0

Views: 82

Answers (1)

Harald Coppoolse
Harald Coppoolse

Reputation: 30502

First of all, if you are still able to change the names of identifiers, my advice would be to stick to the Entity Framework Coding conventions. Doing so, makes it easier for you and others to understand your code.

One of the changes I propose, would be to use singular nouns for single items, and plural nouns for collections. In this case, we would have a class Asset, and your DbContext would have a DbSet of Assets.

Apart from this, your piece of code uses a lot of variables of which we have to guess what they are and what their function is: StartAddress, quantity, client, db. Stick to one convention using your uppercases: is StartAddress a variable? or is it a class name?

Back to your question

From your code I see that there is a not so standard one-to-many relationship between Sensors and Assets. Every Sensor has zero or more Assets, and every Asset may belong to at utmost one Sensor, namely the one that property SensorId refers to. If SensorId is null, then the Asset doesn't belong to any Sensor.

If this is not the case, but every Asset belongs to exactly one Sensor, then consider changing the type of property SensorId to int instead of int?. This way it is impossible to add Sensors that do not belong to any Asset.

From your code, I gather that a Client has a function ReadHoldingRegisters. This method returns an array of integers. The length of the array is probably equal to the value of quantity. Alas you didn't mention whether this is always the case.

StartAddres represents the Id of an existing Sensor. I know the Sensor exists in the database, otherwise it wouldn't have an Id. So I'm not sure why you add the same Sensor four times. If it is already in the database you don't have to Add it anymore, if it is not, you should add it without giving it an Id. In that case SaveChanges will make sure that the Sensor gets an Id.

Sensor already exists

You don't have to Add the Sensor to the database anymore, you only have to add some Assets, one Asset for every Response.

Asset.Value equals the corresponding Response value and every Asset belongs to the Sensor with primary key equal to StartAddress. The foreign key SensorId refers to this Sensor, so SensorId needs to be set to StartAddress.

int[] assetValues = client.ReadHoldingRegisters(startAddress, quantity);

// for every assetValue create an Asset with Value equal to assetValue
// and a foreign key equal to startAddress:
var assetsToAdd = assetValues
    .Select(assetValue => new Asset()
    {
        Value = assetValue,
        SensorId = startAddress,
    });

using (var dbContext = new MyDbContext(...))
{
    // Add the Assets in one call to DbSet.AddRange(IEnumerable)
    dbContext.Assets.AddRange(assetsToAdd);

    // and save the changes:
    dbContext.SaveChanges();
}

Did you see how much easier your code is if you use proper identifiers and proper plurals for sequences and singulars for single items?

Sensor does not exist yet

In this case you'll have to add a Sensor. You can't assign the primary key, so you can't fill Asset.SensorId. Luckily entity framework is smart enough to solve this for you:

int[] assetValues = client.ReadHoldingRegisters(startAddress, quantity);

using (var dbContext = new MyDbContext(...))
{
    // Add one Sensor with all its Assets in one go
    dbContext.Sensors.Add(new Sensor()
    {
        // fill the Sensor properties that you know.
        // don't fill the Id
        ...

        Assets = assetValues
                 .Select(assetValue => new Asset()
                 {
                      Value = assetValue,
                      // no need to fill SensorId, Entity framework will do that for you
                      ... // if needed: fill other Asset properties
                 })
                 .ToList(),
    });
    dbContext.SaveChanges(); 
}

If desired you can do this in two steps:

using (var dbContext = new MyDbContext(...))
{
    // Add one Sensor without Assets
    var addedSensor = dbContext.Sensors.Add(new Sensor()
    {
        // fill the Sensor properties that you know.
        // don't fill the Id, nor property Assets
        ...
    });

    // Add the Assets in one call to DbSet.AddRange(IEnumerable)
    dbContext.Assets.AddRange(assetValues.Select(assetValue => new Asset()
                     {
                         Value = assetValue,
                         Sensor = addedSensor,
                     }));
    dbContext.SaveChanges(); 
}

Upvotes: 2

Related Questions