1

I'm building this app at night after work and have been struggling with this design problem for a week or two now.

I'm building a program that has 44 different types of entries and requires the ability to create a custom type.

Because users might change the fields in a particular type of entry and/or define their own, my first approach of generating an Entity class for each type of entry doesn't seem workable. If users change any of the fields or their version of the schema (subject to validation, of course) then my classes wouldn't really reflect that.

Even if did not allow users to change fields, I want to make sure that data schema changes do not create problems for current data.

In order to build a schema capable of all of this, I have done the following:

dtype

  • id
  • datatype

field

  • id fieldName

  • fieldDataType (linked by foreign key to dtype)

dataStore

    id
    dataText
    dataString
    dataDate
    dataDouble
    dataInt
    fieldID (linked by foreign key to field)
    entryID (linked by foreign key to id field of entries)

types ol>id int

    typeName
    fields

entries

    id
    typeid (linked by foreign key to id of types)

Well, the schema is very denormalized but difficult to work with in ASP.NET MVC.

My second crack at it involved making a class with typed properties to store whichever datatype the entry happened to be.

Custom Class for domain level public class entry { public List dataList = new List();

    public entry(int id)
    {
        kleraDataContext s = new kleraDataContext();
        var dataSet = s.dataStores.Where(c => c.citationID == id);
        foreach (dataStore y in dataSet)
        {
            dataBlob tempd = new dataBlob();

            //We get the data type id
            var temp = s.fields.Where(c => c.id == y.fieldID).First();

            //Get the fieldname and store the data type id for later
            tempd.fieldname = temp.fieldName;
            tempd.dataType = temp.dtype.dataType;

            switch (tempd.dataType)
            {
                case "String":
                    tempd.dString = y.dataString;
                    break;
                case "Text":
                    tempd.dString = y.dataText;
                    break;
                default:
                    //Nothing
                    break;
            }

            this.dataList.Add(tempd);
        }
    }
}

    public class dataBlob
    {
        private string _dString;
        private DateTime _dDate;
        private int _dInt;
        private double _dDouble;
        private object _data;
        private string _fieldname;
        private string _dataType;

       public string dataType
        {
            get
            {
                return _dataType;
            }
            set
            {
                _dataType = value;
            }

        }

        public object data
        {
            get
            {
                return _data;
            }
        }

        public string dString
        {
            get
            {
                return _dString;
            }
            set
            {
                _dString = value;
                _data = value;
            }

        }

        public string fieldname
        {
            get
            {
                return _fieldname;
            }
            set
            {
                _fieldname = value;
            }
        }

        public DateTime dDate
        {
            get
            {
                return _dDate;
            }
            set
            {
                _dDate = value;
                _data = value;
            }

        }

        public double dDouble
        {
            get
            {
                return _dDouble;

            }
            set
            {
                _dDouble = value;
                _data = value;
            }

        }

        public int dInt
        {
            get
            {
                return _dInt;

            }
            set
            {
                _dInt = value;
                _data = value;
            }

        }
    }
}

Note several problems with this.

  1. I'm having trouble getting a generic enough property to store the data regardless of what field type it is in the physical structure. Ideally, data's accessor would just retrieve whatever the datatype happened to be.
  2. I still don't have a good enough way to provide ASP.NET MVC's views with a coherent enough model so that the presentation code does not have to do parsing. Ideally, the view would just get an object with a list of fields and with their corresponding data.
  3. Related to #2, I can't seem to figure out an appropriate way of persisting changes. Writing a query and having it return the fields to the view could be done. Because each field is not a strongly typed accessor, I'm not sure how to persist the change from the view to the model. Naively, I've thought of inserting a key in a hidden span and using a Dictionary object in the controller to map edits/creation.

Thoughts?

Ron

1
  • I havent much time, thats why i didn't analyze your question enough, but wanted to say that in very extreme situation you can use c# in hyperdynamic way by building temporary assembly on fly from string. Have done that with success. Commented May 31, 2009 at 5:28

1 Answer 1

1

While I am not exactly sure of your ultimate goal, I may have an option for you. You need a highly dynamic "entity" which will allow your users to create their own data structures. Imperative languages like C# do not lend themselves well to such a thing...and even with a dynamic language, I think you'll likely run into some difficulties. However, XML is an excellent way to represent dynamic data structures in an ad-hoc, runtime-creatable way.

If you are using SQL Server, I recommend you create a simpler type, as depicted below, and store it in a table that uses the 'xml' data type for one of the columns:

public class DynamicEntity
{
    public int ID { get; set; }
    public string TypeName { get; set; }
    public XDocument DynamicContent { get; set; }
}

The above entity could be stored in the following table:

CREATE TABLE DynamicEntity
(
    ID int IDENTITY(1,1) NOT NULL,
    NAME varchar(50) NOT NULL,
    DynamicContent xml NULL
)

Given SQL Server's xml capabilities, you will still be able to query the data in that xml column. Not only that, if you want your users custom structures to be validated against a schema, you could also put that schema in the database and 'type' your xml column against that schema. Using an XML column in SQL Server does come with come caveats, but it might be a simple solution to your otherwise complicated problem.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.