0

I am new to LINQ and and come up with the below to add new information to my DB using LINQ and EF5 but I am sure there is a more efficant, better, way to do this I just don't know it. I was hoping to get some input on what I can do to acceive the same but with less/more efficant code.

            using (var db = new FullContext())
            {
                if (ddlItemType.SelectedValue == "Other")
                {
                    var NewItemType = new ItemType { Name = tbNewType.Text };
                    db.ItemTypes.Add(NewItemType);
                    db.SaveChanges();
                }

                if (ddlRegion.SelectedValue == "Other")
                {
                    var NewRegion = new ReleaseRegion { Name = tbNewRegion.Text };
                    db.Regions.Add(NewRegion);
                    db.SaveChanges();


                }

                var NewItemTypeID = byte.Parse((from i in db.ItemTypes
                                                where i.Name == tbNewType.Text
                                                select new { i.ID }).ToString());

                var NewRegionID = byte.Parse((from r in db.Regions
                                              where r.Name == tbNewRegion.Text
                                              select new { r.ID }).ToString());

                var NewItem = new Item
                {
                    Name = tbItemName.Text,
                    TypeID = NewItemTypeID,
                    RegionID = NewRegionID,
                    Condition = ddlCondition.SelectedValue.ToString(),
                    UPC = tbUPC.Text,
                    ISBN = tbISBN.Text,
                    IsColleciton = cbIsCollection.Checked,
                    CollectionID = Convert.ToInt16(ddlCollection.SelectedValue),
                    Notes = tbNotes.Text
                };

                db.Items.Add(NewItem);
                db.SaveChanges();
            }

Item.cs:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace FFCollection.DAL
{
    [Table("Items")]
    public class Item
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Int16 ID { get; set; }

        [Required]
        public string Name { get; set; }

        public byte TypeID { get; set; }

        [ForeignKey("TypeID")]
        public virtual ItemType Type { get; set; }

        public byte RegionID { get; set; }

        [ForeignKey("RegionID")]
        public virtual ReleaseRegion Region { get; set; }

        [Required]
        public string Condition { get; set; }

        public string UPC { get; set; }

        public string ISBN { get; set; }

        public string Notes { get; set; }

        [Required]
        public Boolean IsColleciton { get; set; }

        public Int16 CollectionID { get; set; }

        [ForeignKey("CollectionID")]
        public virtual Item InCollectionID { get; set; }
    }
}

ItemType.cs:

using System.ComponentModel.DataAnnotations.Schema;

namespace FFCollection.DAL
{
    public class ItemType
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public byte ID { get; set; }

        public string Name { get; set; }
    }
}

The databinding to DDL:

using (var db = new FullContext())
            {
                ddlItemType.DataSource = (from t in db.ItemTypes
                                          select new { t.ID, t.Name }).ToList();
                ddlItemType.DataTextField = "Name";
                ddlItemType.DataValueField = "ID";
                ddlItemType.DataBind();
                ddlItemType.Items.Insert(0, new ListItem("Other", "Other"));
}

2 Answers2

2

Part of the trouble isn't Linq, it's how you're using EF. Based on that example code you're using it as a data layer wrapper rather than an ORM. When constructing an object graph you should deal with the objects where you can, not foreign key IDs. The power of an ORM is that you can deal specifically with object graphs that are mapped to data, so that when you tell the ORM to save an object (and it's associated relatives) the ORM takes out all of the work of inserting/updating new records and wiring up keys. You're doing all that extra work in code, where an ORM like EF should allow you to accomplish what you want with a handful of lines.

For a start, when dealing with combo boxes, bind them to a data structure that includes the lookup value's ID that you can resolve instances of existing ItemTypes or Regions to associate with your new Item. (or in the case of selections of "other".

What I'd be looking at would be to bind the combo boxes to ItemType/Regions with the "Other" being a specific place-holder that the code will substitute with a new object if selected based on entries in the text fields. Then rather than saving the new objects before appending to the "Item", you simply set the references and save the Item which should cascade insert operations for the new lookup objects.

Steve Py
  • 26,149
  • 3
  • 25
  • 43
  • Unfortuatnly the only way for me to learn EF is to teach it to my self by finding very old, outdated blogs/articals that are not ment to teach people how to use EF and figure it out my self. I have never used ORMs I am simply trying to convert my site from ADO.Net to EF and honitsly most of your first paragraph makes no sense to me. As for the combos they are bound to ID/Name pairs but the the "other" option is to allow people to add new regions/types and the only way I know to do that is to allow the option in ddl and have them type in a text box. If you know a better way please show me. –  Nov 29 '12 at 01:02
  • I really want to learn how to do this stuff and do it properly but I am still a student in university and my job as a jr. dev does not touch any projects using EF. The only way I really have to learn this stuff is by working on my own home projects and over the past few years of working on my own projects I have learned that I can pick this stuff up very fast by looking at examples and working to adapt them to my site. –  Nov 29 '12 at 01:12
  • No worries. Picking up technologies on your own can be frustrating, but well worth the effort. What I am referring to is a Many-to-1 relationship. This link should give you some ideas relative to how you are laying out your objects and mapping. http://stackoverflow.com/questions/11197546/ef-fluent-api-many-to-one-relation-navigation-property-is-not-fetched In his example the mapping is fairly sound, just his problem was a rogue initialization. – Steve Py Nov 29 '12 at 03:57
  • I am glad you understand and are willing to work with me. When I created the classes in EF I set these up as a 1 to 1 relationship (and looking at the DB in SQL is is setup like that) Where one item can only be of one type. I have not looked at fulent API so most of the code in the link is not understanable to me I have update my first posting to include the databind to the DDL and the two classes to make the tables incase that helps you, but I am still stuck on how I can clean the code up. –  Nov 29 '12 at 14:17
0

After this code executes EF will automatically put an ID into your NewItemType entity. You don't need to go and find it again, you could just say NewItemType.ID. This will only work after you have already called db.SaveChanges().

if (ddlItemType.SelectedValue == "Other")
{
    var NewItemType = new ItemType { Name = tbNewType.Text };
    db.ItemTypes.Add(NewItemType);
    db.SaveChanges();
}
Daniel Gabriel
  • 3,939
  • 2
  • 26
  • 37