0

I have 2 related tables, which are Assemblies and Parts.

My Assembly class:

public class Assembly{
  public int Id { get; set; }
  public string No{ get; set; }
  public string Name { get; set; }

  public int? ParentId { get; set; }
  public Assembly Parent { get; set; }

  public List<Assembly> Children { get; set}
  public List<Part> Parts { get; set; }
}

My Part class:

public class Part{
   public int Id { get; set; }
   public string No { get; set; }
   public string Name { get; set; }
   public string Image { get; set; }

   public int AssemblyId { get; set;}
   public Assembly Assembly { get; set; }
}

What am I doing is, first I'm creating Assemblies in a controller. Then when I create an Assembly, a file upload page is opening, then I upload an Excell files and map the excell data to my Part Object as a reference to my Assembly object.(Every parts AssemblyId will be the AssemblyId comes from route)

But there is a huge problem with this, because most of the Assemblies have the same Part or Parts in its Parts list.

For example, lets say there is a part, Part No : 555 , Part Name : Axle.

And lets assume that Im going to create 5 Assembly in my project. And every Assembly will going to have data imported from different excell files.

And each excell contains the same Part which its Part No : 555 and Part Name: Axle but obviously with different AssemblyId(FK).

But still in my Database there are so many Parts which has the same information with its duplicates but the little difference is that their AssemblyId column is different and referencing to another Assembly in the AssemblyId.

What I'd like to achive is to avoid from this situation...

I don't want to repeat my data. Actually I think a solution but Im not sure that its a good solution.. I might do a "if" statement and check, while uploading data from excell, if a Part with those information aleady exists in the database I might not upload that specific row to the table, and use the part which is already exist. But I think this will slows down my project.

I hope I've asked it clearly..

Burak
  • 467
  • 4
  • 16
  • *many Parts which has the same information with its duplicates but (...) their AssemblyId column is different* The big flaw here is that you should have implemented this as a many-to-many relationship. – Gert Arnold Nov 02 '19 at 15:35
  • I wanted to give them a spesific AssemblyId identifier, but now I can see that it is totally the wrong way... Actually I have to try this in a N-N relationship.. Thank you. – Burak Nov 03 '19 at 01:45

2 Answers2

1

This is a relational design issue, your Parts table should not have reference to the Assembly table. Assembly Table should have the reference only to the parts ids.

Please consider :

  • To have one table for the assembly definition, this table shouldn't have parts involved, only assemblies.
  • To have one table for the Assembly-Part Relation.

public class Assembly_Part{ public int AssemblyId { get; set;} public int PartId { get; set; } }

  • To have Parts Table with no relation to the assemblies (remove AssemblyId from your Parts Table)

if you don't want some parts to be part of a specific assembly then you should create a extra relation for parts id-assemblies.

When you send data to the DB you should send an assembly and parts id related, not the part definition.

Then Your part definition process should take care of the part creation, not the assembly creation process.

When adding parts to the assembly you may have a distinction between new parts and old parts if both process performed together.

This is my optimal scenario:

  • You want to create an assembly, your process will define a new AssemblyId and allow you to pick parts to be included in the Assembly. In DB you will only add records to Assembly Table.

  • In case you need a new part, that part should be created in a different process, this process will handle the part creation and validation for existing parts. In DB you will only add records to Parts Table.

  • When loading parts for an assembly you will create a List that will contain all part related to the current searches, no duplication.

Please refer to : Database Design Best Practices.

Locke1211
  • 61
  • 4
0

You can override the equals method for whichever class you are looking at (Part in this case) and compare the fields you care about to see if one Part is the same as another in the context of your app. See the following for a simple example:

  public class Part 
  {
    public string Name { get; set; }

    public DateTime? InactiveDate { get; set; }

    public int AssemblyId {get; set;}

    public override bool Equals(object obj)
    {
      Part yVal = (Part) obj;

      if (yVal == null)
      {
        return false;
      }

      // compare each of the values we care about. i.e: NOT comparing AssemblyId
      return this.Name == yVal.Name
        && this.InactiveDate == yVal.InactiveDate;
    }

You would then use this when youre going to save a new part to the database, see if any existing part .Equals any existing Part:

var existingPart = db.Parts.SingleOrDefault(x => myPartToSave.Equals(x))

if(existingPart != null)
{
    myAssemblyToSave.Parts.Remove(myPartToSave);
    myAssemblyToSave.Parts.Add(existingPart);
}

//then save your part as you normally would

If it does, then save your Assembly using the existing Part and if it doesn't, save the Assembly and Part as you normally would .

Note: before implementing this, it's probably a good idea to write a sql script (or console app, or whatever youre most comfortable with) to get rid of any duplicates that currently exist

Another Note: It's also best practice to override the GetHashCode method when you override Equals. I won't go into detail here why since it's beyond the scope of this question- you should be able to easily find information on this. There's a pretty good thread right here on SO about it

GregH
  • 5,125
  • 8
  • 55
  • 109
  • I will try this as fast as I can, thank you for your answers. – Burak Nov 02 '19 at 15:25
  • Checking the equals was a good Idea, but still cannot actually solved the problem for me... The main struggle in here is that Assemblies are Self Referencing Data structure(parent-child relationship) and every assembly has its own parts list... – Burak Nov 06 '19 at 00:28
  • i understand assemblies and parts have a parent child relationship. there's still no reason (at least in your question) why this wont work. Also, unless you have a typo in your post, `Assembly` is not self referencing (this would involve teh Assembly class having a property of type Assembly in it) see https://flylib.com/books/en/2.255.1/self_referential_classes.html – GregH Nov 06 '19 at 02:47
  • This is a self referencing structure, I forgot to write it when I was creating the question, it was a mistake... Let me edit. But thank you. – Burak Nov 06 '19 at 12:50
  • that doesnt affect the proposed solution at all- this still works. if you post the actual code you're using to try this then we can help troubleshoot your issue. if not, theres not much else I can do here. No matter what you're doing, when a new part is going to be saved, you need to check if it exists in the db already and use the existing one if it's there in order to prevent duplicates. – GregH Nov 06 '19 at 13:05