Create a part attachment

I have a custom program I am creating to link engineers to Epicor. So far I have been able to return any data they want from customer info or part data. I also used IMPL integration to create a project. Now I am trying to create a part attachment I use the part adapter GetNewPartAttach and it errors out telling me failed to enable constraints. Anyone do anything like this before? any suggestions?

Part Attachment is oddly tricky business. It might get a little easier if the Document Type is always the same. Sounds like you’ve already did the Trace. Is it possible that you’re entering the same document twice?

Mark W.

Yep - load the master part record first using GetById, then it should work.

Ok i did PartAdapter.GetByID(partnumber) and it now got past that. I am now trying to figure out what tables need to be updated in the part dataset. I tried using PartAdapter.TableNames to get the table names but I only got a list of numbers. Any Help Is greatly appreciated. I would really like to know where to find the info I am looking for also.

Turn on tracing, then run thru the steps to add an attachment and you will see all of the calls/tables needed.

Ok I found it and I believe I have entered data everywhere creating an attachment does through the system. Now I am throwing the error Must Have a FileName or Description. Below is my code and I tested the args and the FilePath is there just like the logs. Am I missing setting data in another table. I had to turn on a few settings in the trace log so I can see the full data set and all but I don’t see where else the specific file I am putting in is called other than this table. The error obviously triggers on the PA update. PA is declared prior as a PartAdapter. Thanks for your help so far. I ran the trace log before but not with the dataset which now seems so obvious but I am learning a lot so thank you very much.

if (PA.GetNewPartAttch(args[0]))
int A = PA.PartData.Tables[“PartRevAttch”].Rows.Count - 1;

                PA.PartData.Tables["PartRevAttch"].Rows[A]["Company"] = "OurCompany";
                PA.PartData.Tables["PartRevAttch"].Rows[A]["PartNum"] = args[0];
                PA.PartData.Tables["PartRevAttch"].Rows[A]["RevisionNum"] = args[1];
                PA.PartData.Tables["PartRevAttch"].Rows[A]["DrawDesc"] = args[2];
                PA.PartData.Tables["PartRevAttch"].Rows[A]["FileName"] = args[3];

Here’s the gist of what we do. I’m looking for a better way (still trying to get REST going) because this method consumes a license.

    public static XFileRefAdapter x = null;

    public static PartAdapter p = null;

            epiSession = new Ice.Core.Session(gUsername, gPassword, Ice.Core.Session.LicenseType.DataAdministration, gSysConfigFile);

            oTrans = new ILauncher(epiSession);

            x = new XFileRefAdapter(oTrans);



        x.ClearData(); //clear the record

        if (x.GetNewXFileRef())


            x.XFileRefData.XFileRef[0]["Company"] = "My Company Name";

            x.XFileRefData.XFileRef[0]["XFileName"] = fullpath;

            x.XFileRefData.XFileRef[0]["XFileDesc"] = filename;

            x.XFileRefData.XFileRef[0]["DocTypeId"] = doctype;

            x.XFileRefData.XFileRef[0]["BaseFileName"] = filename;

// custom fields we use

            x.XFileRefData.XFileRef[0]["date01"] = DateTime.Now;

            x.XFileRefData.XFileRef[0]["shortchar01"] = "Source=DocImagingApp ("+Environment.UserName+")";





            p = new PartAdapter(oTrans);



            p.GetByID(objectData);  // objectData is the part number passed into this route


            attachIndex = p.PartData.PartAttch.Count - 1;

            p.PartData.PartAttch[attachIndex]["Company"] = company.ToUpper();

            p.PartData.PartAttch[attachIndex]["DrawDesc"] = filename;

            p.PartData.PartAttch[attachIndex]["DocTypeID"] = doctype;

            p.PartData.PartAttch[attachIndex]["FileName"] = fullpath;

            p.PartData.PartAttch[attachIndex]["ForeignSysRowID"] = p.PartData.Part[0]["SysRowID"];

            p.PartData.PartAttch[attachIndex]["XFileRefNum"] = xFileRefNum;


- Steve

Ok So I Have to create a File reference before I try to add it to the part attachment. This sounds easy enough. How do you return the xFileRefNum. That is system generated.

oops - yep, after creating the xFileRef record:

           int xFileRefNum = Convert.ToInt32(x.XFileRefData.XFileRef[0]["XFileRefNum"]);

Thank you chris and steve. Both of you helped me get through it I had a problem with the code posted I was looking at the part rev attach table for the row count but updating the part attach. To sum up what needs to happen for part attach or even part rev attachment you need to create the file reference first then load the part into the part adapter then call the new part attach or part rev attach and fill in the data. This is alot different than I am used to with Epicor but it does make sense now that I am through it. If anyone wants the code please let me know and I can send it your way or post on here.


You may want to add a check to make sure the file reference doesn’t already exist, if so, just use that ID in the attach record.

Mark W.

I was thinking about that In this instance that may happen and the path may be the same. Thanks for the catch. I will now add that to my code.