依赖对象创建

时间:2017-04-03 12:39:30

标签: c# entity-framework asp.net-web-api

环境:

我在Webapi工作。下面是2个实体类;

public class Class1
{
    public Class1()
    {
        this.items = new HashSet<Class2>();
    }
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Class2> items { get; set; }
}

public class Class2
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Class1Id { get; set; }

    public virtual Class1 class1 { get; set; }
}

业务层: buniess层具有以下代码;

public class Class1Logic : IClass1Logic
{
    private readonly IClass1Repository _repo;
    public Class1Logic(IClass1Repository repository)
    {
        _repo = repository;
    }

    public async Task<bool> AddClass1ItemAsync(Class1 item)
    {
        _repo.Add(item);
        bool status = await _repo.SaveAsync();
        return status;
    }

    public async Task<Class1> GetClass1ItemAsync(int id)
    {
        return await _repo.GetAsync(id);
    }
}

public class Class2Logic : IClass1Logic
{
    private readonly IClass2Repository _repo;
    public Class2Logic(IClass2Repository repository)
    {
        _repo = repository;
    }

    public async Task<bool> AddClass2ItemAsync(Class2 item)
    {
        _repo.Add(item);
        bool status = await _repo.SaveAsync();
        return status;
    }

    public async Task<Class2> GetClass2ItemAsync(int id)
    {
        return await _repo.GetAsync(id);
    }
}

的ViewModels:

public class Class1Model
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Class2Model
{
    public int Id { get; internal set; }
    public string Name { get; set; }
    public int Class1Id { get; set; }
    public string Class1Name { get; internal set; }
}

控制器:

有两个类似于Class1Controller和Class2Controller的控制器。两者都有CRUD操作。

[RoutePrefix("api/class1items")]
public class Class1Controller : ApiController
{
    private readonly IClass1Logic _class1Logic;
    private ModelFactory TheFactory;
    public Class1Controller(IClass1Logic class1Logic)
    {
        _class1Logic = class1Logic;
        TheFactory = new ModelFactory();
    }

    [Route("")]
    public async Task<IHttpActionResult> Post(Class1Model class1Model)
    {
        var item = TheFactory.Parse(class1Model);
        bool result = await _class1Logic.AddClassItemAsync(item);
        if (!result)
        {
            return BadRequest("Error");
        }
        string uri = Url.Link("GetLabById", new { id = item.Id });
        return Created(uri, TheFactory.Create(item));
    }

    [Route("{id:int}", Name = "GetClass1ItemById")]
    public async Task<IHttpActionResult> GetClass1Item(int id)
    {
        Class1 item = await _class1Logic.GetClassItemAsync(id);
        if (item == null)
        {
            return NotFound();
        }
        return Ok(TheFactory.Create(item));
    }

}

[RoutePrefix("api/class2items")]
public class Class2Controller : ApiController
{
        private readonly IClass2Logic _class2Logic;
        private ModelFactory TheFactory;
        public Class2Controller(IClass2Logic class2Logic)
        {
            _class2Logic = class2Logic;
            TheFactory = new ModelFactory();
        }

        [Route("")]
        public async Task<IHttpActionResult> Post(Class2Model class2Model)
        {
            var item = TheFactory.Parse(class2Model);
        ***//Here item should include Class1 object even if user give ClassId in class2Model***

        bool result = await _class2Logic.AddClassItemAsync(item);
            if (!result)
            {
                return BadRequest("Error");
            }
            string uri = Url.Link("GetClass2ItemById", new { id = item.Id });
            return Created(uri, TheFactory.Create(item));
        }

    }

Class1没有任何依赖。所以所有操作都很好。在Class2Controller post方法中,我得到了如下的模型对象来创建Class2。

{
  "id": 0,
  "name": "string",
  "class1Id": 1
}

理解:

我需要在创建记录后将此viewmodel返回给用户。记录创建成功,但是当映射到viewmodel时,我得到了null异常,因为Class1对象不在Class2对象中。

为了获得包含class1对象的Class2对象,我需要在请求对象中给出class1Object。

为此,我需要在请求对象中找到Class1Id的Class1对象。

ViewMapper代码:

public class ModelFactory
{
    public Class1Model Create(Class1 item)
    {
        return new Class1Model
        {
            Id = item.Id,
            Name = item.Name
        };
    }
    public Class2Model Create(Class2 item)
    {
        return new Class2Model
        {
            Id = item.Id,
            Name = item.Name,
            Class1Id = item.class1.Id,
            Class1Name = item.class1.Name
        };
    }
    public  Class1 Parse(Class1Model modelItem)
    {
        return new Class1
        {
            Id = modelItem.Id,
            Name = modelItem.Name
        };
    }
    public Class2 Parse(Class2Model modelItem)
    {
        return new Class2
        {
            Id = modelItem.Id,
            Name = modelItem.Name,
            Class1Id = modelItem.Class1Id,
            ***/*Issue Place*/
            //class1 =  Need to set property by getting object using modelItem.Class1Id***      
        };
    }
}

问题:

现在我需要通过传递Class1Id来调用Class1Controller的get方法。

如何打电话,这是正确的吗?还是我的设计不好?

这是最初的情况。如果我的Class3再次同时具有Class1和Class2,我需要调用Class1和Class2的方法。

请帮助在这种情况下找到正确的解决方案

注意:我在问题区域添加了评论

1 个答案:

答案 0 :(得分:0)

好吧,只是要解决此问题,您需要在保存后手动调用class Program { static void Main(string[] args) { CreateFileStream(); byte[] array1 = new byte[1191980]; byte[] array2 = new byte[1191936]; byte[] array3 = new byte[1191936]; byte[] array4 = new byte[85138]; //Larger size - Can change file name //byte[] array4 = new byte[79462]; //Smaller size - Cannot change file name }//Breakpoint here, try and change the file name C:\FileName.wav to something else private static void CreateFileStream() { FileStream fileStream = new FileStream(@"C:\FileName.wav", FileMode.Open, FileAccess.Read, FileShare.Read); } } 。然而,这看起来不太好。

更优雅的解决方法:

1)如果您需要填写def firstRepeatedWord(string) h_data = Hash.new(0) string.split(" ").each{|x| h_data[x] +=1} h_data.key(h_data.values.max) end 字段,请在获取数据时使用_class1Logic.GetClass1ItemAsync(在存储库中):Class2.Class1

2)你也可以打开LazyLoading for EF - 我认为它应该适用于你的情况。

3)将class1Repo注入class2Logic并在保存后修复class1引用 - 如果你不想启用延迟加载或者在save方法之后将项目与上下文分离

关于设计的想法:

我建议您查看Automapper或simular库而不是Include,其中您将拥有所有映射逻辑

编辑:关于通用存储库:您可以修改dbContext.Set<Class2>().Include(c => c.class1)方法

ModelFactory

IEntity界面:

GetAsync

通过此实现,您可以使用

public async Task<T> GetAsync<T>(int id, params Expression<Func<T, object>>[] includes)
    where T: class, IEntity
{
    var query = context.Set<T>().AsQueryable();

    if (includes.Length > 0)
    {
        query = includes.Aggregate(query,
          (current, include) => current.Include(include));
    }

    return await query.FirstOrDefaultAsync(x => x.Id == id);
}