简体   繁体   中英

Proper way to deal with only utilizing a few properties of a class?

I'm adding to a fairly large program. In this program, there is a class that is mapped from our database that contains all the attributes for each employees. It has things like name, phone number, hire date, and many others; over 40 attributes in all.

Now, for my personal needs, I need to access this data, but I only need to use four or five of the attributes, not all of the ones available. I will be manipulating this "mini-object" in many ways, such as searching, returning results, and things of that nature. Here is a small, made-up example to supplement my explanation.

public class BigEmployee //mapped from database
{
    public string attr1 {get;set;}
    public string attr2 {get;set;}
    public string attr3 {get;set;}
    public string attr4 {get;set;}
    //...etc, until attribute 40
}

public class SmallEmployee //IF THIS EXISTED, this all that I would need
{
    public string attr1 {get;set;} //same as BigEmployee attr1
    public string attr2 {get;set;} //same as BigEmployee attr2
    public string attr3 {get;set;} //same as BigEmployee attr3
}

and an Example Method:

public List<SmallEmployee> GetAllEmployees
{
    return EmployeeList;
}

So, what I'm wondering, is how do I approach this problem? Should I make a separate object that is pulled from the main class? Should I just access the main class each time and force it to only return certain attributes?

Your question can't easily be answered from the information that you've provided. I will try to give some general guidance, though:

It looks like your project is using some form of ORM, whether it's one of the many third-party ORM's (Entity Framework, NHibernate, SimpleData, etc.) or something homegrown. If that's the case, then there's nothing practically wrong with just creating a "lite" version of the same entity in its own class. ORM-generated classes should just be DTO's (data transfer objects), so there should not be any business logic contained within them. The advantage to using such classes is that, depending on the ORM, they can cut down on database traffic (since they're only bringing back the columns that you use).

BUT (and this is a big but)

They are only suitable for read-only use .

Most ORM's rely on saving an entire object or object graph back to the database. They generally do not provide a means of making changes to the database without having the original object in memory in its full ORM-compatible entity form. The most common use for these "lite" classes is for sending back large lists of objects to the user, at which point they'll select one in whatever way is idiomatic to your program, then the program will retrieve the full entity object for editing.

If what you need is full bidirectional support (retrieval alongside insert, update, and delete functionality), then you're practically limited to using the fully entity class.

EDIT Here's an example of using a "lite" entity:

Consider we have an entity named Customer in our context. We need a lite customer that only contains the ID (an int ) and the name (a string ). Just define a class for the lite entity:

public class CustomerLite
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
}

Then use it in a query like this:

var liteCustomers = context.Customers
                    .Where(c => c.Name.StartsWith("Smith, ")
                    .Select(c => new CustomerLite()
                    {
                        CustomerId = c.CustomerId,
                        Name = c.Name
                    })
                    .ToList();

(or, if you prefer query syntax to lambda syntax)

var liteCustomers = (from c in context.Customers
                     where c.Name.StartsWith("Smith, ")
                     select new CustomerLite()
                     {
                         CustomerId = c.CustomerId,
                         Name = c.Name
                     }).ToList();

Yes, that's a good way to do it. It's the way to go if you want to return it as a query directly from the database.

Another method would be to use interfaces:

public interface ISmallEmployee
{
    string attr1 {get;set;} //same as BigEmployee attr1
    string attr2 {get;set;} //same as BigEmployee attr2
    string attr3 {get;set;} //same as BigEmployee attr3
}

public class BigEmployee : ISmallEmployee
{
    ...
}

However, the ORM probably won't recognize this directly, so you'd have to query all BigEmployee 's and cast them to ISmallEmployee in C#.

You could also make SmallEmployee a base class of BigEmployee , you would need to take a bit of care in how you configure your ORM to interperet this.

I think you are on the right track.

Look up the I in SOLID http://www.codeproject.com/Articles/60845/The-SOLID-Object-Oriented-Programming-OOP-Prin

Map your main object to whatever projection your client need in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM